fix: mobile nav close button + CI Gatekeeper auth
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Successful in 2m25s
Build & Deploy / 🏗️ Build (push) Successful in 4m56s
Build & Deploy / 🚀 Deploy (push) Successful in 15s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 5m3s
Build & Deploy / 🔔 Notify (push) Successful in 3s

- Add explicit close (×) button inside mobile nav overlay
  - Was unreachable because header's hamburger was behind overlay z-index
  - New button lives inside the overlay at full z-index visibility
- Fix check-forms.ts: authenticate via Gatekeeper login form
  - Old approach: inject raw password as session cookie (didn't work)
  - New approach: navigate to protected page, detect Gatekeeper gate,
    fill password form and submit to get a real server-signed session cookie
  - Fixes E2E form tests that failed because pages returned Gatekeeper HTML
This commit is contained in:
2026-02-28 19:25:53 +01:00
parent a2cf9791ae
commit 089ce13c59
2 changed files with 46 additions and 10 deletions

View File

@@ -352,6 +352,29 @@ export default function Header() {
ref={mobileMenuRef}
inert={isMobileMenuOpen ? undefined : true}
>
{/* Close Button inside overlay */}
<div className="flex justify-end p-6 pt-8">
<button
className="touch-target p-2 rounded-xl bg-white/10 border border-white/20 text-white hover:bg-white/20 transition-all duration-300"
aria-label={t('toggleMenu')}
onClick={() => {
setIsMobileMenuOpen(false);
trackEvent(AnalyticsEvents.BUTTON_CLICK, {
type: 'mobile_menu',
action: 'close',
});
}}
>
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<nav className="flex-grow flex flex-col justify-center items-center p-8 space-y-8">
{menuItems.map((item, idx) => (
<div

View File

@@ -66,16 +66,29 @@ async function main() {
const page = await browser.newPage();
// 3. Inject Gatekeeper session bypassing auth screens
console.log(`\n🛡 Injecting Gatekeeper Session...`);
await page.setCookie({
name: 'klz_gatekeeper_session',
value: gatekeeperPassword,
domain: new URL(targetUrl).hostname,
path: '/',
httpOnly: true,
secure: targetUrl.startsWith('https://'),
});
// 3. Authenticate through Gatekeeper login form
console.log(`\n🛡 Authenticating through Gatekeeper...`);
try {
// Navigate to a protected page so Gatekeeper redirects us to the login screen
await page.goto(contactUrl, { waitUntil: 'networkidle0', timeout: 30000 });
// Check if we landed on the Gatekeeper login page
const isGatekeeperPage = await page.$('input[name="password"]');
if (isGatekeeperPage) {
await page.type('input[name="password"]', gatekeeperPassword);
await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 30000 }),
page.click('button[type="submit"]'),
]);
console.log(`✅ Gatekeeper authentication successful!`);
} else {
console.log(`✅ Already authenticated (no Gatekeeper gate detected).`);
}
} catch (err: any) {
console.error(`❌ Gatekeeper authentication failed: ${err.message}`);
await browser.close();
process.exit(1);
}
let hasErrors = false;