Skip to content

πŸ§ͺ Google Calendar Integration - Guida Testing Completa ​

Guida step-by-step per testare tutte le funzionalitΓ  Google Calendar (Fasi 1-5).


πŸ“‹ PRE-REQUISITI ​

Setup Environment ​

  1. 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
  2. .env Configuration

    env
    GOOGLE_CALENDAR_CLIENT_ID=your_client_id_here
    GOOGLE_CALENDAR_CLIENT_SECRET=your_client_secret_here
  3. Queue Worker

    bash
    php artisan queue:work --queue=google-calendar
    # oppure
    php artisan horizon
  4. Cache Redis (opzionale, migliora performance)

    bash
    redis-server

βœ… FASE 1: OAuth + Setup Base ​

Test 1.1: Connessione Google Calendar ​

Steps:

  1. Login al dashboard
  2. Vai a /settings/calendar
  3. Verifica stato "Non connesso" (pallino grigio)
  4. Click "Connetti Google Calendar"
  5. Aspettato: Redirect a Google OAuth
  6. Autorizza l'applicazione
  7. Aspettato: Redirect back con messaggio success
  8. Verifica stato "Connesso" (pallino verde)
  9. Verifica "Token valido fino al..." mostrato

Verifica Database:

sql
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 != NULL
  • google_refresh_token != NULL
  • google_calendar_sync_enabled = true
  • google_token_expires_at > now

Test 1.2: Disconnessione ​

Steps:

  1. Dalla pagina /settings/calendar
  2. Click "Disconnetti"
  3. Conferma nel modal
  4. Aspettato: Redirect + messaggio success
  5. Verifica stato "Non connesso"

Verifica Database:

sql
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:

  1. Connetti Google Calendar (Test 1.1)
  2. Crea BookingPage:
    • Name: "Test Meeting"
    • Duration: 30 min
    • Sync Google Calendar: ON
    • Seleziona calendario primario

Steps:

  1. Apri booking page pubblica: /booking/test-meeting
  2. Seleziona data domani
  3. Verifica slot disponibili mostrati
  4. Seleziona slot (es. 10:00)
  5. Compila form:
  6. Submit booking

Aspettato:

  • Messaggio "Prenotazione confermata"
  • Email conferma ricevuta

Verifica Google Calendar:

  1. Apri Google Calendar web
  2. Verifica evento creato per domani alle 10:00
  3. Titolo: "Test Meeting con Mario Rossi"
  4. Attendees: mario@test.com
  5. Verifica invito inviato a mario@test.com

Verifica Database:

sql
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 != NULL
  • google_synced_at != NULL
  • Evento visibile su Google Calendar
  • Invito ricevuto da ospite

Setup:

  1. Booking page con meeting_type = "video"
  2. video_platform = "google_meet"

Steps:

  1. Prenota appuntamento video
  2. Attendi job completion (~30 sec)

Verifica:

sql
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:

  1. Crea evento manualmente su Google Calendar per domani 14:00-15:00
  2. Booking page con sync ON

Steps:

  1. Apri /booking/test-meeting
  2. Seleziona data domani
  3. 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:

  1. Crea appointment con Google sync

Steps:

  1. Vai in dashboard /appointments
  2. Edit appointment
  3. Cambia orario: 10:00 β†’ 11:00
  4. Save
  5. 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:

  1. Delete appointment in Blade
  2. Attendi job

Verifica Google Calendar:

  • Evento eliminato
  • Email "Evento cancellato" ricevuta

Test 3.3: Webhook Google β†’ Blade (Cancellazione) ​

Steps:

  1. Crea appointment con Google sync
  2. Apri Google Calendar web
  3. Elimina evento manualmente
  4. Attendi webhook (~5-10 sec)

Verifica Blade:

sql
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:

  1. Crea appointment
  2. Su Google Calendar, sposta evento a orario diverso
  3. 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:

  1. Vai a /i-miei-calendari
  2. Verifica "Calendario Principale" listato
  3. Click "Connetti Nuovo Calendario"
  4. OAuth flow Google
  5. Nella pagina Google, seleziona calendario diverso (es. Work, Personal)
  6. Autorizza

Post-OAuth:

  1. Vai a /i-miei-calendari
  2. Edit secondo calendario:
    • Label: "Team Sales"
    • Sync Mode: "Solo Lettura"
    • Save

Verifica Database:

sql
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:

  1. 2 calendari connessi (primary + secondary)
  2. Evento su secondary calendar domani 10:00-11:00

Steps:

  1. Edit BookingPage

  2. Tab "Automazione CRM"

  3. Sync Google = ON

  4. Seleziona ENTRAMBI i calendari

  5. Save

  6. Apri booking page pubblica

  7. Seleziona domani

  8. 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:

  1. Secondary calendar in read_only mode
  2. BookingPage con entrambi selezionati

Steps:

  1. Ospite prenota slot 14:00
  2. Attendi job

Verifica:

  1. Google Calendar primary: evento creato βœ…
  2. Google Calendar secondary: nessun evento ❌ (solo lettura)
  3. 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:

  1. 3 calendari read_write:
    • Mario (priority: 0)
    • Luigi (priority: 1)
    • Anna (priority: 2)
  2. BookingPage con team_scheduling_mode = "priority"
  3. Associa tutti e 3 calendari

Test Case A: Mario Disponibile

  1. Nessun evento su Mario domani 10:00
  2. Ospite prenota 10:00

Aspettato:

  • Evento creato su calendario Mario

Test Case B: Mario Busy, Luigi Disponibile

  1. Crea evento su calendario Mario 10:00-11:00
  2. 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:

  1. Same calendari setup Test 5.1
  2. team_scheduling_mode = "round_robin"

Steps:

  1. Prenota 1Β° appuntamento β†’ Assegnato a Mario (0 assignments)
  2. Prenota 2Β° appuntamento β†’ Assegnato a Luigi (0 assignments)
  3. Prenota 3Β° appuntamento β†’ Assegnato a Anna (0 assignments)
  4. Prenota 4Β° appuntamento β†’ Assegnato a Mario (1 assignment, minimo)

Verifica Stats:

sql
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:

  1. Same calendari
  2. 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:

  1. 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:

  1. 3 calendari team
  2. 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:

  1. Prenota 3 appuntamenti in round-robin
  2. Vai a database:
sql
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):

  1. Crea 3 User Google Accounts (o usa calendari condivisi)

  2. Login come Admin

  3. 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
  4. 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):

  1. 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)
  2. Ospite 2 prenota (slot 11:00):

    • Same flow
    • Nome: Cliente B
    • βœ… Assigned to Luigi (0 assignments)
  3. Ospite 3 prenota (slot 14:00):

    • Same flow
    • Nome: Cliente C
    • βœ… Assigned to Anna (0 assignments)
  4. Ospite 4 prenota (slot 15:00):

    • Same flow
    • Nome: Cliente D
    • βœ… Assigned to Mario (1 assignment = minimo)

Verifica:

  1. Google Calendar Mario:

    • 2 eventi (10:00, 15:00)
    • Entrambi con Google Meet link
    • Inviti inviati
  2. Google Calendar Luigi:

    • 1 evento (11:00)
  3. Google Calendar Anna:

    • 1 evento (14:00)
  4. Email Ospiti:

    • Tutti ricevono invito calendario
    • Tutti hanno Google Meet link
  5. Database Stats:

    sql
    SELECT 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:

  1. Prenota appointment domani 10:00
  2. Verifica evento su Google Calendar
  3. Su Google Calendar: Sposta evento a 11:00
  4. Attendi webhook (~10 sec)

Verifica Blade:

sql
SELECT start_time, end_time, google_synced_at 
FROM appointments 
WHERE google_event_id = 'xxx';

Aspettato:

  • start_time = tomorrow 11:00
  • google_synced_at recente

Test Sync: Cancellazione su Google ​

Steps:

  1. Prenota appointment
  2. Su Google Calendar: Elimina evento
  3. Attendi webhook

Verifica Blade:

  • Appointment.status = "cancelled"
  • cancellation_reason = "Evento eliminato da Google Calendar"

πŸ“Š TEST ANALYTICS ​

Team Stats ​

Query:

sql
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:

  1. Disconnetti internet
  2. Prenota appointment
  3. Riconnetti dopo 1 min

Aspettato:

  • Appointment creato in Blade βœ…
  • Job enqueued
  • Retry automatico 3x
  • Dopo 3 fail: Notification admin

Test: Token Expired ​

Steps:

  1. Manualmente set google_token_expires_at = past
  2. Prenota appointment

Aspettato:

  • Auto-refresh token
  • Job completato success

Test: Calendario Non Configurato ​

Steps:

  1. BookingPage sync = ON
  2. Nessun calendario associato
  3. 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:

  1. Domain verification su Google Cloud Console
  2. HTTPS in produzione (Google requirement)
  3. Log: storage/logs/laravel.log cerca "Google Calendar webhook"

Fix locale (ngrok):

bash
ngrok http 80
# Usa URL ngrok come redirect_uri + webhook

Eventi Non Creati ​

Check:

  1. Queue worker running?
  2. Check failed_jobs table
  3. Log: cerca "CreateGoogleCalendarEventJob"

Debug:

bash
php artisan queue:work --queue=google-calendar --tries=1 --timeout=120

Availability Non Filtrata ​

Check:

  1. Cache: php artisan cache:clear
  2. Calendari associati a BookingPage?
  3. Calendari is_active = true?

Debug:

sql
SELECT * FROM booking_page_calendars 
WHERE booking_page_id = your_id;

πŸ“ˆ PERFORMANCE TESTING ​

Load Test: 100 Concurrent Bookings ​

bash
# Setup Apache Bench
ab -n 100 -c 10 -p booking.json -T application/json \
   http://your-domain.test/booking/test-meeting

Aspettato:

  • Tutti job queued
  • No database deadlocks
  • Cache hit rate > 80%

Cache Performance ​

Verifica:

bash
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! πŸš€

Realizzato con ❀️ da DScom