π§ͺ Google Calendar Integration - Guida Testing Completa β
Guida step-by-step per testare tutte le funzionalitΓ Google Calendar (Fasi 1-5).
π PRE-REQUISITI β
Setup Environment β
Google Cloud Console
- Vai a: https://console.cloud.google.com/
- Crea nuovo progetto o usa esistente
- Abilita Google Calendar API
- Crea OAuth 2.0 credentials
- Aggiungi redirect URI:
http://your-domain.test/oauth/google-calendar/callback - Scarica credenziali
.env Configuration
envGOOGLE_CALENDAR_CLIENT_ID=your_client_id_here GOOGLE_CALENDAR_CLIENT_SECRET=your_client_secret_hereQueue Worker
bashphp artisan queue:work --queue=google-calendar # oppure php artisan horizonCache Redis (opzionale, migliora performance)
bashredis-server
β FASE 1: OAuth + Setup Base β
Test 1.1: Connessione Google Calendar β
Steps:
- Login al dashboard
- Vai a
/settings/calendar - Verifica stato "Non connesso" (pallino grigio)
- Click "Connetti Google Calendar"
- Aspettato: Redirect a Google OAuth
- Autorizza l'applicazione
- Aspettato: Redirect back con messaggio success
- Verifica stato "Connesso" (pallino verde)
- Verifica "Token valido fino al..." mostrato
Verifica Database:
SELECT
google_access_token,
google_refresh_token,
google_calendar_sync_enabled,
google_token_expires_at
FROM users
WHERE id = your_user_id;β Success Criteria:
google_access_token!= NULLgoogle_refresh_token!= NULLgoogle_calendar_sync_enabled= truegoogle_token_expires_at> now
Test 1.2: Disconnessione β
Steps:
- Dalla pagina
/settings/calendar - Click "Disconnetti"
- Conferma nel modal
- Aspettato: Redirect + messaggio success
- Verifica stato "Non connesso"
Verifica Database:
SELECT google_access_token FROM users WHERE id = your_user_id;
-- Deve essere NULLβ FASE 2: Creazione Eventi + Availability β
Test 2.1: Creazione Evento Google β
Setup:
- Connetti Google Calendar (Test 1.1)
- Crea BookingPage:
- Name: "Test Meeting"
- Duration: 30 min
- Sync Google Calendar: ON
- Seleziona calendario primario
Steps:
- Apri booking page pubblica:
/booking/test-meeting - Seleziona data domani
- Verifica slot disponibili mostrati
- Seleziona slot (es. 10:00)
- Compila form:
- Nome: Mario Rossi
- Email: mario@test.com
- Phone: +39 123 456 7890
- Submit booking
Aspettato:
- Messaggio "Prenotazione confermata"
- Email conferma ricevuta
Verifica Google Calendar:
- Apri Google Calendar web
- Verifica evento creato per domani alle 10:00
- Titolo: "Test Meeting con Mario Rossi"
- Attendees: mario@test.com
- Verifica invito inviato a mario@test.com
Verifica Database:
SELECT
id,
guest_name,
guest_email,
google_event_id,
google_synced_at,
status
FROM appointments
ORDER BY created_at DESC
LIMIT 1;β Success Criteria:
google_event_id!= NULLgoogle_synced_at!= NULL- Evento visibile su Google Calendar
- Invito ricevuto da ospite
Test 2.2: Google Meet Link Automatico β
Setup:
- Booking page con
meeting_type= "video" video_platform= "google_meet"
Steps:
- Prenota appuntamento video
- Attendi job completion (~30 sec)
Verifica:
SELECT google_meet_link FROM appointments ORDER BY created_at DESC LIMIT 1;Apri invito calendario:
- Verifica link Google Meet presente
- Click link β Deve aprire Google Meet
β Success Criteria:
google_meet_link!= NULL- Link formato:
https://meet.google.com/xxx-yyyy-zzz - Link funzionante
Test 2.3: Availability Check con Google Busy Times β
Setup:
- Crea evento manualmente su Google Calendar per domani 14:00-15:00
- Booking page con sync ON
Steps:
- Apri
/booking/test-meeting - Seleziona data domani
- Scroll lista slot disponibili
Aspettato:
- Slot 14:00 NON mostrato (busy su Google)
- Slot 14:30 NON mostrato (overlap)
- Slot 13:30 mostrato (before busy time)
- Slot 15:00 mostrato (after busy time)
β Success Criteria:
- Busy times Google rispettati
- No double booking possibile
β FASE 3: Sync Bidirezionale β
Test 3.1: Update da Blade β Google β
Setup:
- Crea appointment con Google sync
Steps:
- Vai in dashboard
/appointments - Edit appointment
- Cambia orario: 10:00 β 11:00
- Save
- Attendi job (~30 sec)
Verifica Google Calendar:
- Evento spostato a 11:00
- Email "Evento modificato" ricevuta da ospite
β Success Criteria:
- Evento aggiornato su Google
- Notifica inviata
Test 3.2: Delete da Blade β Google β
Steps:
- Delete appointment in Blade
- Attendi job
Verifica Google Calendar:
- Evento eliminato
- Email "Evento cancellato" ricevuta
Test 3.3: Webhook Google β Blade (Cancellazione) β
Steps:
- Crea appointment con Google sync
- Apri Google Calendar web
- Elimina evento manualmente
- Attendi webhook (~5-10 sec)
Verifica Blade:
SELECT status, cancellation_reason
FROM appointments
WHERE google_event_id = 'xxx';Aspettato:
status= "cancelled"cancellation_reason= "Evento eliminato da Google Calendar"
β Success Criteria:
- Sync automatico cancellazione
- Status aggiornato in Blade
Test 3.4: Webhook Google β Blade (Modifica Orario) β
Steps:
- Crea appointment
- Su Google Calendar, sposta evento a orario diverso
- Attendi webhook
Verifica Blade:
- Appointment.start_time aggiornato
- Appointment.end_time aggiornato
google_synced_at= recent
β Success Criteria:
- Sincronizzazione automatica
- Orari allineati
β FASE 4: Multi-Calendario β
Test 4.1: Connessione Secondo Calendario β
Steps:
- Vai a
/i-miei-calendari - Verifica "Calendario Principale" listato
- Click "Connetti Nuovo Calendario"
- OAuth flow Google
- Nella pagina Google, seleziona calendario diverso (es. Work, Personal)
- Autorizza
Post-OAuth:
- Vai a
/i-miei-calendari - Edit secondo calendario:
- Label: "Team Sales"
- Sync Mode: "Solo Lettura"
- Save
Verifica Database:
SELECT
label,
google_calendar_id,
sync_mode,
is_primary
FROM user_calendars
WHERE user_id = your_id;Aspettato:
- 2 calendari listati
- Uno primary (read_write)
- Uno secondary (read_only)
Test 4.2: Multi-Calendar Availability β
Setup:
- 2 calendari connessi (primary + secondary)
- Evento su secondary calendar domani 10:00-11:00
Steps:
Edit BookingPage
Tab "Automazione CRM"
Sync Google = ON
Seleziona ENTRAMBI i calendari
Save
Apri booking page pubblica
Seleziona domani
Verifica slot
Aspettato:
- Slot 10:00 NON mostrato (busy su secondary)
- Slot 10:30 NON mostrato (overlap)
- Altri slot mostrati normalmente
β Success Criteria:
- Busy times aggregati da ENTRAMBI i calendari
- Eventi creati solo su primary (read_write)
Test 4.3: Read-Only Calendar β
Setup:
- Secondary calendar in read_only mode
- BookingPage con entrambi selezionati
Steps:
- Ospite prenota slot 14:00
- Attendi job
Verifica:
- Google Calendar primary: evento creato β
- Google Calendar secondary: nessun evento β (solo lettura)
- Appointment.google_event_id salvato
β Success Criteria:
- Read-only rispettato
- Eventi solo su calendar write-enabled
β FASE 5: Team Scheduling β
Test 5.1: Priority Mode β
Setup:
- 3 calendari read_write:
- Mario (priority: 0)
- Luigi (priority: 1)
- Anna (priority: 2)
- BookingPage con team_scheduling_mode = "priority"
- Associa tutti e 3 calendari
Test Case A: Mario Disponibile
- Nessun evento su Mario domani 10:00
- Ospite prenota 10:00
Aspettato:
- Evento creato su calendario Mario
Test Case B: Mario Busy, Luigi Disponibile
- Crea evento su calendario Mario 10:00-11:00
- Ospite prenota 10:00
Aspettato:
- Evento creato su calendario Luigi (fallback priority 1)
Verifica Log:
assigned_to_calendar: "Mario" (o "Luigi")
scheduling_mode: "priority"Test 5.2: Round-Robin Mode β
Setup:
- Same calendari setup Test 5.1
- team_scheduling_mode = "round_robin"
Steps:
- Prenota 1Β° appuntamento β Assegnato a Mario (0 assignments)
- Prenota 2Β° appuntamento β Assegnato a Luigi (0 assignments)
- Prenota 3Β° appuntamento β Assegnato a Anna (0 assignments)
- Prenota 4Β° appuntamento β Assegnato a Mario (1 assignment, minimo)
Verifica Stats:
SELECT
uc.label,
bpc.total_assignments,
bpc.last_assigned_at
FROM booking_page_calendars bpc
JOIN user_calendars uc ON uc.id = bpc.user_calendar_id
WHERE booking_page_id = your_booking_page_id
ORDER BY bpc.total_assignments;Aspettato:
- Mario: 2 assignments
- Luigi: 1 assignment
- Anna: 1 assignment
β Success Criteria:
- Distribuzione equa
- Chi ha meno assignments prioritΓ
Test 5.3: Load Balanced Mode β
Setup:
- Same calendari
- team_scheduling_mode = "load_balanced"
Scenario:
- Mario: 5 assignments, ultimo 1 ora fa
- Luigi: 4 assignments, ultimo 24 ore fa
- Anna: 6 assignments, ultimo 48 ore fa
Steps:
- Prenota nuovo appuntamento
Aspettato:
- Assegnato a Mario (score piΓΉ basso)
- Score Mario: 500 + 99 = 599
- Score Luigi: 400 + 0 = 400
- Score Anna: 600 + 0 = 600
Ops, Luigi ha score piΓΉ basso!
Aspettato CORRETTO:
- Assegnato a Luigi
Test 5.4: Collective Mode β
Setup:
- 3 calendari team
- team_scheduling_mode = "collective"
Test Case A: Tutti Disponibili
- Nessun evento su nessun calendario domani 10:00
- Slot 10:00 mostrato
- Prenota β Evento su primo calendario (priority 0)
Test Case B: Uno Busy
- Evento su Luigi domani 10:00-11:00
- Slot 10:00 NON mostrato (anche se Mario e Anna liberi)
β Success Criteria:
- Slot solo se TUTTI disponibili
- Perfetto per team meetings
Test 5.5: Assignment Stats Tracking β
Steps:
- Prenota 3 appuntamenti in round-robin
- Vai a database:
SELECT
uc.label,
bpc.total_assignments,
bpc.last_assigned_at,
bpc.priority
FROM booking_page_calendars bpc
JOIN user_calendars uc ON uc.id = bpc.user_calendar_id
WHERE booking_page_id = your_id
ORDER BY bpc.total_assignments DESC;Aspettato:
- total_assignments incrementato
- last_assigned_at aggiornato
- Distribuito secondo algoritmo
π TEST END-TO-END COMPLETO β
Scenario Completo: Sales Team Demo β
Setup (10 min):
Crea 3 User Google Accounts (o usa calendari condivisi)
Login come Admin
Connetti 3 Calendari:
/i-miei-calendariβ Connetti- Calendario 1: Label "Mario Sales", read_write, primary
- Calendario 2: Label "Luigi Sales", read_write
- Calendario 3: Label "Anna Sales", read_write
Crea BookingPage "Demo Prodotto":
- Duration: 30 min
- Weekly hours: Lun-Ven 9-17
- Tab "Automazione CRM":
- Sync Google = ON
- Seleziona tutti e 3 calendari
- Team Scheduling = "round_robin"
- Save
Test Flow (15 min):
Ospite 1 prenota (slot 10:00):
- Apri
/booking/demo-prodotto - Seleziona domani 10:00
- Nome: Cliente A, Email: clienteA@test.com
- Submit
- β Assigned to Mario (0 assignments)
- Apri
Ospite 2 prenota (slot 11:00):
- Same flow
- Nome: Cliente B
- β Assigned to Luigi (0 assignments)
Ospite 3 prenota (slot 14:00):
- Same flow
- Nome: Cliente C
- β Assigned to Anna (0 assignments)
Ospite 4 prenota (slot 15:00):
- Same flow
- Nome: Cliente D
- β Assigned to Mario (1 assignment = minimo)
Verifica:
Google Calendar Mario:
- 2 eventi (10:00, 15:00)
- Entrambi con Google Meet link
- Inviti inviati
Google Calendar Luigi:
- 1 evento (11:00)
Google Calendar Anna:
- 1 evento (14:00)
Email Ospiti:
- Tutti ricevono invito calendario
- Tutti hanno Google Meet link
Database Stats:
sqlSELECT uc.label, bpc.total_assignments FROM booking_page_calendars bpc JOIN user_calendars uc ON uc.id = bpc.user_calendar_id;- Mario: 2
- Luigi: 1
- Anna: 1
β Success Criteria:
- Round-robin funziona
- Distribuzione equa
- Google Meet attivo
- Sync completo
π TEST SYNC BIDIREZIONALE β
Test Sync: Modifica su Google β
Steps:
- Prenota appointment domani 10:00
- Verifica evento su Google Calendar
- Su Google Calendar: Sposta evento a 11:00
- Attendi webhook (~10 sec)
Verifica Blade:
SELECT start_time, end_time, google_synced_at
FROM appointments
WHERE google_event_id = 'xxx';Aspettato:
start_time= tomorrow 11:00google_synced_atrecente
Test Sync: Cancellazione su Google β
Steps:
- Prenota appointment
- Su Google Calendar: Elimina evento
- Attendi webhook
Verifica Blade:
- Appointment.status = "cancelled"
- cancellation_reason = "Evento eliminato da Google Calendar"
π TEST ANALYTICS β
Team Stats β
Query:
SELECT
uc.label AS team_member,
bpc.total_assignments,
bpc.last_assigned_at,
bpc.priority,
COUNT(a.id) AS actual_appointments
FROM booking_page_calendars bpc
JOIN user_calendars uc ON uc.id = bpc.user_calendar_id
LEFT JOIN appointments a ON a.booking_page_id = bpc.booking_page_id
WHERE bpc.booking_page_id = your_id
GROUP BY bpc.id
ORDER BY bpc.total_assignments DESC;Verifica:
- total_assignments accurato
- Correlazione con actual_appointments
- last_assigned_at recente per assignment recenti
β οΈ TEST ERROR HANDLING β
Test: Google API Down β
Steps:
- Disconnetti internet
- Prenota appointment
- Riconnetti dopo 1 min
Aspettato:
- Appointment creato in Blade β
- Job enqueued
- Retry automatico 3x
- Dopo 3 fail: Notification admin
Test: Token Expired β
Steps:
- Manualmente set
google_token_expires_at= past - Prenota appointment
Aspettato:
- Auto-refresh token
- Job completato success
Test: Calendario Non Configurato β
Steps:
- BookingPage sync = ON
- Nessun calendario associato
- Prenota
Aspettato:
- Appointment creato β
- Warning notification
- Messaggio: "Configura almeno un calendario"
π― CHECKLIST FINALE β
Fase 1 β
- [ ] OAuth redirect funziona
- [ ] Token salvati encrypted
- [ ] Disconnect funziona
- [ ] UI stato connessione
Fase 2 β
- [ ] Eventi creati su Google
- [ ] Inviti inviati a ospiti
- [ ] Google Meet link generato
- [ ] Availability check busy times
- [ ] Caching funziona (5min)
Fase 3 β
- [ ] Update Blade β Google
- [ ] Delete Blade β Google
- [ ] Webhook ricevuti
- [ ] Sync cancellazioni Google β Blade
- [ ] Sync modifiche Google β Blade
Fase 4 β
- [ ] Connessione N calendari
- [ ] Read-only vs Read-write
- [ ] Aggregazione busy times multi-cal
- [ ] UI gestione calendari
- [ ] Migration dati esistenti
Fase 5 β
- [ ] Priority assignment
- [ ] Round-robin distribution
- [ ] Load balancing
- [ ] Collective availability
- [ ] Stats tracking
- [ ] UI team scheduling mode
π TROUBLESHOOTING β
Webhook Non Ricevuti β
Check:
- Domain verification su Google Cloud Console
- HTTPS in produzione (Google requirement)
- Log:
storage/logs/laravel.logcerca "Google Calendar webhook"
Fix locale (ngrok):
ngrok http 80
# Usa URL ngrok come redirect_uri + webhookEventi Non Creati β
Check:
- Queue worker running?
- Check failed_jobs table
- Log: cerca "CreateGoogleCalendarEventJob"
Debug:
php artisan queue:work --queue=google-calendar --tries=1 --timeout=120Availability Non Filtrata β
Check:
- Cache:
php artisan cache:clear - Calendari associati a BookingPage?
- Calendari is_active = true?
Debug:
SELECT * FROM booking_page_calendars
WHERE booking_page_id = your_id;π PERFORMANCE TESTING β
Load Test: 100 Concurrent Bookings β
# Setup Apache Bench
ab -n 100 -c 10 -p booking.json -T application/json \
http://your-domain.test/booking/test-meetingAspettato:
- Tutti job queued
- No database deadlocks
- Cache hit rate > 80%
Cache Performance β
Verifica:
redis-cli KEYS "google_busy_calendar*"
# Deve mostrare cache entriesβ ACCEPTANCE CRITERIA (TUTTE LE FASI) β
FunzionalitΓ β
- [ ] OAuth flow completo
- [ ] Eventi Google creati automaticamente
- [ ] Google Meet link funzionante
- [ ] Inviti calendario ricevuti
- [ ] Availability real-time accurate
- [ ] No double booking
- [ ] Sync bidirezionale (Blade β Google)
- [ ] Multi-calendario supportato
- [ ] Team scheduling 4 modalitΓ
- [ ] Stats tracking
Performance β
- [ ] Job < 5 sec (95 percentile)
- [ ] Availability query < 300ms
- [ ] Cache hit rate > 80%
- [ ] Webhook response < 200ms
Reliability β
- [ ] Retry automatico funziona
- [ ] Graceful degradation (se Google down)
- [ ] No data loss
- [ ] Backward compatibility
UX β
- [ ] UI intuitiva
- [ ] Helper text chiari
- [ ] Error messages utili
- [ ] Loading states appropriati
π REPORT RISULTATI β
Dopo testing, compilare:
FASE 1: [ ] PASS / [ ] FAIL
FASE 2: [ ] PASS / [ ] FAIL
FASE 3: [ ] PASS / [ ] FAIL
FASE 4: [ ] PASS / [ ] FAIL
FASE 5: [ ] PASS / [ ] FAIL
Issues trovati: ___________
Performance: ___________
Note: ___________Happy Testing! π