Gate testing API for staging E2E
This commit is contained in:
@@ -13,7 +13,7 @@ class TestCheckoutController extends Controller
|
||||
{
|
||||
public function latest(Request $request): JsonResponse
|
||||
{
|
||||
abort_unless(app()->environment(['local', 'testing']), 404);
|
||||
abort_unless(config('e2e.testing_enabled'), 404);
|
||||
|
||||
$validated = $request->validate([
|
||||
'email' => ['nullable', 'string', 'email'],
|
||||
@@ -66,7 +66,7 @@ class TestCheckoutController extends Controller
|
||||
CheckoutWebhookService $webhooks,
|
||||
CheckoutSession $session
|
||||
): JsonResponse {
|
||||
abort_unless(app()->environment(['local', 'testing']), 404);
|
||||
abort_unless(config('e2e.testing_enabled'), 404);
|
||||
|
||||
$validated = $request->validate([
|
||||
'event_type' => ['nullable', 'string'],
|
||||
|
||||
@@ -16,7 +16,7 @@ class TestCouponController extends Controller
|
||||
{
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
abort_unless(app()->environment(['local', 'testing']), 404);
|
||||
abort_unless(config('e2e.testing_enabled'), 404);
|
||||
|
||||
$payload = $request->input('coupons');
|
||||
$definitions = collect(is_array($payload) ? $payload : [])
|
||||
|
||||
@@ -15,7 +15,7 @@ class TestEventController extends Controller
|
||||
{
|
||||
public function joinToken(Request $request, EventJoinTokenService $tokens): JsonResponse
|
||||
{
|
||||
abort_unless(app()->environment(['local', 'testing']), 404);
|
||||
abort_unless(config('e2e.testing_enabled'), 404);
|
||||
|
||||
$validated = $request->validate([
|
||||
'event_id' => ['nullable', 'integer'],
|
||||
|
||||
@@ -20,7 +20,7 @@ class TestGuestEventController extends Controller
|
||||
{
|
||||
public function store(Request $request, EventJoinTokenService $joinTokens): JsonResponse
|
||||
{
|
||||
abort_unless(app()->environment(['local', 'testing']), 404);
|
||||
abort_unless(config('e2e.testing_enabled'), 404);
|
||||
|
||||
$validated = $request->validate([
|
||||
'slug' => ['nullable', 'string', 'max:100'],
|
||||
|
||||
@@ -10,7 +10,7 @@ class TestMailboxController extends Controller
|
||||
{
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
abort_unless(app()->environment(['local', 'testing']), 404);
|
||||
abort_unless(config('e2e.testing_enabled'), 404);
|
||||
|
||||
return response()->json([
|
||||
'data' => Mailbox::all(),
|
||||
@@ -19,7 +19,7 @@ class TestMailboxController extends Controller
|
||||
|
||||
public function destroy(): JsonResponse
|
||||
{
|
||||
abort_unless(app()->environment(['local', 'testing']), 404);
|
||||
abort_unless(config('e2e.testing_enabled'), 404);
|
||||
|
||||
Mailbox::flush();
|
||||
|
||||
|
||||
24
app/Http/Middleware/EnsureE2ETestingAccess.php
Normal file
24
app/Http/Middleware/EnsureE2ETestingAccess.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class EnsureE2ETestingAccess
|
||||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if (! config('e2e.testing_enabled')) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$token = config('e2e.testing_token');
|
||||
if ($token && $request->header('X-Testing-Token') !== $token) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
[DispatchGuestNotificationPush::class, 'handle']
|
||||
);
|
||||
|
||||
if ($this->app->environment(['local', 'testing'])) {
|
||||
if (config('e2e.testing_enabled')) {
|
||||
EventFacade::listen(
|
||||
MessageSent::class,
|
||||
[Mailbox::class, 'record']
|
||||
|
||||
@@ -14,7 +14,7 @@ class Mailbox
|
||||
|
||||
public static function record(MessageSent $event): void
|
||||
{
|
||||
if (! app()->environment(['local', 'testing'])) {
|
||||
if (! config('e2e.testing_enabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
6
config/e2e.php
Normal file
6
config/e2e.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'testing_enabled' => env('E2E_TESTING_ENABLED', in_array(env('APP_ENV'), ['local', 'testing'], true)),
|
||||
'testing_token' => env('E2E_TESTING_TOKEN'),
|
||||
];
|
||||
@@ -10,6 +10,9 @@ export default defineConfig({
|
||||
reporter: 'html',
|
||||
use: {
|
||||
baseURL: process.env.E2E_BASE_URL ?? 'https://test-y0k0.fotospiel.app',
|
||||
extraHTTPHeaders: process.env.E2E_TESTING_TOKEN
|
||||
? { 'X-Testing-Token': process.env.E2E_TESTING_TOKEN }
|
||||
: undefined,
|
||||
trace: 'on-first-retry',
|
||||
headless: true,
|
||||
screenshot: 'only-on-failure',
|
||||
|
||||
@@ -353,6 +353,6 @@ Route::prefix('v1')->name('api.v1.')->group(function () {
|
||||
|
||||
});
|
||||
|
||||
if (app()->environment(['local', 'testing'])) {
|
||||
if (config('e2e.testing_enabled')) {
|
||||
require __DIR__.'/testing.php';
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
use App\Http\Controllers\Testing\TestCheckoutController;
|
||||
use App\Http\Controllers\Testing\TestCouponController;
|
||||
use App\Http\Controllers\Testing\TestGuestEventController;
|
||||
use App\Http\Controllers\Testing\TestEventController;
|
||||
use App\Http\Controllers\Testing\TestGuestEventController;
|
||||
use App\Http\Controllers\Testing\TestMailboxController;
|
||||
use App\Http\Middleware\EnsureE2ETestingAccess;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::prefix('_testing')->group(function () {
|
||||
Route::prefix('_testing')->middleware(EnsureE2ETestingAccess::class)->group(function () {
|
||||
Route::get('/mailbox', [TestMailboxController::class, 'index'])->name('testing.mailbox.index');
|
||||
Route::delete('/mailbox', [TestMailboxController::class, 'destroy'])->name('testing.mailbox.destroy');
|
||||
|
||||
|
||||
36
tests/Feature/TestingApiAccessTest.php
Normal file
36
tests/Feature/TestingApiAccessTest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
class TestingApiAccessTest extends TestCase
|
||||
{
|
||||
public function test_testing_routes_are_blocked_when_disabled(): void
|
||||
{
|
||||
config([
|
||||
'e2e.testing_enabled' => false,
|
||||
'e2e.testing_token' => 'secret-token',
|
||||
]);
|
||||
|
||||
$this->withHeader('X-Testing-Token', 'secret-token')
|
||||
->getJson('/api/_testing/mailbox')
|
||||
->assertNotFound();
|
||||
}
|
||||
|
||||
public function test_testing_routes_require_token_when_enabled(): void
|
||||
{
|
||||
config([
|
||||
'e2e.testing_enabled' => true,
|
||||
'e2e.testing_token' => 'secret-token',
|
||||
]);
|
||||
|
||||
$this->getJson('/api/_testing/mailbox')
|
||||
->assertNotFound();
|
||||
|
||||
$this->withHeader('X-Testing-Token', 'secret-token')
|
||||
->getJson('/api/_testing/mailbox')
|
||||
->assertOk()
|
||||
->assertJsonStructure(['data']);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ test.describe('Marketing auth flows', () => {
|
||||
await page.getByLabel(/Telefon/i).fill('+49123456789');
|
||||
await page.getByLabel(/Adresse/i).fill('Teststr. 1, 12345 Berlin');
|
||||
await page.getByLabel(/Username/i).fill(username);
|
||||
await page.getByLabel(/^Passwort$/i).fill(password);
|
||||
await page.getByLabel(/Passwort bestätigen/i).fill(password);
|
||||
await page.fill('input[name="password"]', password);
|
||||
await page.fill('input[name="password_confirmation"]', password);
|
||||
await page.locator('#privacy_consent').check();
|
||||
|
||||
await page.getByRole('button', { name: /^Registrieren$/i }).click();
|
||||
|
||||
@@ -6,8 +6,8 @@ test.describe('Marketing hero CTA smoke', () => {
|
||||
|
||||
await page.goto('/');
|
||||
|
||||
const cta = page.getByRole('link', {
|
||||
name: /Pakete entdecken|Jetzt loslegen|Discover Packages|Get started now/i,
|
||||
const cta = page.locator('#hero').getByRole('link', {
|
||||
name: /Pakete ansehen|Pakete entdecken|Discover Packages/i,
|
||||
});
|
||||
|
||||
await expect(cta).toBeVisible();
|
||||
@@ -22,12 +22,12 @@ test.describe('Marketing hero CTA smoke', () => {
|
||||
await page.goto('/packages');
|
||||
|
||||
const cta = page.getByRole('link', {
|
||||
name: /Pakete entdecken|Lieblingspaket sichern|Discover Packages|Explore top packages/i,
|
||||
name: /Pakete entdecken|Discover Packages/i,
|
||||
});
|
||||
|
||||
await expect(cta).toBeVisible();
|
||||
await cta.click();
|
||||
|
||||
await expect(page.locator('#endcustomer')).toBeVisible();
|
||||
await expect(page.locator('#packages-showcase')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,7 +18,9 @@ test.describe('Marketing frontend smoke', () => {
|
||||
}
|
||||
|
||||
await expect(page.getByRole('heading', { level: 1, name: /Dein Event|Fotospiel/i })).toBeVisible();
|
||||
const heroCta = page.getByRole('link', { name: /paket|packages|starten|ausprobieren/i }).first();
|
||||
const heroCta = page.locator('#hero').getByRole('link', {
|
||||
name: /Pakete ansehen|Pakete entdecken|Discover Packages/i,
|
||||
});
|
||||
await expect(heroCta).toBeVisible();
|
||||
|
||||
await heroCta.click();
|
||||
|
||||
@@ -66,9 +66,9 @@ test.describe('Standard package checkout with Paddle completion', () => {
|
||||
await page.goto('/de/packages');
|
||||
|
||||
const standardDetailsButton = page
|
||||
.getByRole('heading', { name: /^Standard$/ })
|
||||
.locator('..')
|
||||
.getByRole('button', { name: /Details/i })
|
||||
.locator('[data-slot="card"]')
|
||||
.filter({ hasText: /Standard/i })
|
||||
.getByRole('button', { name: /Details ansehen|Details anzeigen|View details/i })
|
||||
.first();
|
||||
|
||||
await expect(standardDetailsButton).toBeVisible();
|
||||
|
||||
Reference in New Issue
Block a user