import json import os import sys import time from datetime import datetime, timedelta from pathlib import Path from playwright.sync_api import sync_playwright from backend.security import auth # Generate admin JWT token = auth.create_access_token(data={"sub": "master", "role": "admin"}) artifacts_dir = Path(r"C:\Users\rcnai\.gemini\antigravity-ide\brain\687690db-36e3-42ea-89a5-947c15851521") screenshot1_path = str(artifacts_dir / "schedule_modal_conflict.png") screenshot2_path = str(artifacts_dir / "schedule_list_conflicts.png") with sync_playwright() as p: browser = p.chromium.launch(headless=True) context = browser.new_context(viewport={"width": 1280, "height": 800}) page = context.new_page() print("[1] Navigating to http://localhost:8000/...") page.goto("http://localhost:8000/") page.wait_for_load_state("networkidle") # Set JWT in localStorage and reload print("[2] Injecting auth token...") page.evaluate(f"localStorage.setItem('pabot_jwt', '{token}');") page.reload() page.wait_for_load_state("networkidle") time.sleep(1) # Check if auth shield is hidden shield_display = page.evaluate("document.getElementById('authShield').style.display") print(f"Auth shield display: {shield_display}") # Navigate to Schedule page print("[3] Switching to Schedule tab...") page.click("button:has-text('Schedule')") time.sleep(1) # Check current schedule view state init_html = page.inner_text("#schedEventsList") print(f"Initial Schedule List:\n{init_html.strip()}\n") # Click "+ New Event" print("[4] Clicking '+ New Event'...") page.click("button:has-text('New Event')") page.wait_for_selector("#calendarEventModal.show", state="visible") # Today's date in local YYYY-MM-DD now = datetime.now() start_dt = now.replace(minute=0, second=0, microsecond=0) + timedelta(hours=1) end_dt = start_dt + timedelta(hours=1) start_str = start_dt.strftime("%Y-%m-%dT%H:%M") end_str = end_dt.strftime("%Y-%m-%dT%H:%M") print(f"[5] Filling Event 1: 'Sprint Architecture Sync' from {start_str} to {end_str}...") page.fill("#eventModalTitleInput", "Sprint Architecture Sync") page.fill("#eventModalStartInput", start_str) page.fill("#eventModalEndInput", end_str) page.select_option("#eventModalCategoryInput", "work") # Submit Event 1 page.click("#calendarEventModal button[type='submit']") page.wait_for_selector("#calendarEventModal", state="hidden") time.sleep(1.5) # Verify Event 1 appears in the list list_text_1 = page.inner_text("#schedEventsList") print(f"[6] Events List after adding Event 1:\n{list_text_1.strip()}\n") assert "Sprint Architecture Sync" in list_text_1, "Event 1 did not appear in the list!" assert "No events scheduled for this period" not in list_text_1, "Still showing 'No events scheduled'!" # Create Event 2: Overlapping event print("[7] Clicking '+ New Event' for second overlapping event...") page.click("button:has-text('New Event')") page.wait_for_selector("#calendarEventModal.show", state="visible") # Overlapping slot: starts 30 mins after Event 1 starts overlap_start_dt = start_dt + timedelta(minutes=30) overlap_end_dt = overlap_start_dt + timedelta(hours=1) overlap_start_str = overlap_start_dt.strftime("%Y-%m-%dT%H:%M") overlap_end_str = overlap_end_dt.strftime("%Y-%m-%dT%H:%M") print(f"[8] Filling Event 2: 'Emergency Client Sync' from {overlap_start_str} to {overlap_end_str}...") page.fill("#eventModalTitleInput", "Emergency Client Sync") page.fill("#eventModalStartInput", overlap_start_str) page.fill("#eventModalEndInput", overlap_end_str) # Trigger input change and conflict check page.evaluate("checkModalEventConflict();") time.sleep(1) # Check modal conflict banner modal_conflict_style = page.evaluate("document.getElementById('modalConflictAlert').style.display") modal_conflict_text = page.inner_text("#modalConflictText") print(f"[9] Modal Conflict Alert Display: {modal_conflict_style}") print(f" Modal Conflict Alert Text: '{modal_conflict_text}'") # Take screenshot of modal with conflict warning page.screenshot(path=screenshot1_path) print(f" Saved screenshot to {screenshot1_path}") # Submit Event 2 print("[10] Submitting overlapping event...") page.click("#calendarEventModal button[type='submit']") page.wait_for_selector("#calendarEventModal", state="hidden") time.sleep(1.5) # Verify both events and global conflict banner on schedule page list_text_2 = page.inner_text("#schedEventsList") global_conflict_display = page.evaluate("document.getElementById('schedGlobalConflictBanner').style.display") global_conflict_text = page.inner_text("#schedGlobalConflictBanner") print(f"[11] Events List after adding Overlapping Event 2:\n{list_text_2.strip()}\n") print(f"[12] Global Conflict Banner Display: {global_conflict_display}") print(f" Global Conflict Banner Text: '{global_conflict_text.strip()}'") # Check conflict cards and pills conflict_cards_count = page.evaluate("document.querySelectorAll('.sched-event-card.has-conflict').length") conflict_pills_count = page.evaluate("document.querySelectorAll('.pill.rose').length") print(f"[13] Conflict Cards Count: {conflict_cards_count}") print(f" Conflict Pills Count: {conflict_pills_count}") page.screenshot(path=screenshot2_path) print(f" Saved screenshot to {screenshot2_path}") browser.close() print("\n=== SCHEDULE & CONFLICT TEST COMPLETED SUCCESSFULLY ===")