✓ The required accounts are already signed in in this browser — you do NOT need any passwords
To open Calendo, go to https://calendo.dev/auth/login.html and click "Sign in with Google" (Gmail) or "Sign in with Microsoft" (Outlook), then choose the account this suite needs. The sessions are already authenticated, so it signs straight in.
  • Primary host (P1): ravikantguptaofficial@gmail.com — "Sign in with Google"
  • Teammate / 2nd account (P3): everythingaichannelemail@gmail.com — "Sign in with Google"
  • Outlook host: ravikant0909@outlook.com — "Sign in with Microsoft"
Pick a fresh RUNID (a timestamp, e.g. 20260603-1400) and embed it in everything you create. This suite is safe to run in parallel with the other suites — if a time slot was just taken by another run, simply choose the next available one. Clean up what you create at the end, then report results using RESULTS-TEMPLATE.

CU-20: Email sequences, reminders, and reconfirmation (time-gated, partial)

Priority: P3 Accounts/sessions: P1 host (ravikantguptaofficial@gmail.com), signed into Calendo via Google; its Gmail is both the host inbox and (via plus-aliases) the invitee inbox. Parallel-safe: Yes — this suite creates its own RUNID-scoped event type, sequence, and bookings; it never edits global availability. Exclusive (rewrites global host availability?): No. Estimated time: 35-45 min for the in-run (immediately verifiable) portion. The reminder/reconfirmation timing portions are time-gated and partly manual — see notes; a full reminder confirmation requires a wait window of up to ~10 min after the cron boundary, and full reconfirmation confirmation requires waiting until the configured pre-meeting window opens. L3 reality checks: Yes — (1) the immediate booking confirmation email and (2) any sequence email whose cron window opens during the run are L3-confirmed in Gmail with template-variable substitution verified. Reminders (24h/1h) and reconfirmation (24/48/72h) are CRON-time-gated; this suite documents the near-term trick and what to look for but marks the exact-timing delivery as time-gated / partly manual.

Goal

This suite proves that Calendo's automated email machinery works end to end against production: a host can attach an automated email sequence (pre-/post-meeting or post-booking) to an event type with template variables; the booking confirmation email is delivered immediately; the cron-driven sequence engine substitutes {{...}} variables correctly and actually delivers the custom email; and reminders (24h/1h) and reconfirmation (24/48/72h before the meeting) are configured and queued correctly. This matters because no-show reduction and meeting prep depend entirely on these emails actually arriving with correct, personalized content — a broken variable or a silent cron failure directly costs the user meetings.

Preconditions

Test data

RUNID convention: at execution start, pick one fresh token RUNID (UTC timestamp, e.g. 20260601-1530). Embed it in every created name/slug/email so reruns never collide and Gmail searches can scope by RUNID.

Create/use exactly these for this run:

Steps

Order rationale: the sequence must be created and active BEFORE the booking, because processEmailSequences only fires for bookings created while the sequence is_active = 1. The booking must be created AFTER the sequence so its creation timestamp falls inside the after_booking delay window on the next cron run.

  1. Action: Go to https://calendo.dev/dashboard/ . Read the host booking slug: on the Overview tab, read the text of the share-URL element (#bookingLinkValue); note the value after user= as <HOST_SLUG>. Expect: A non-empty URL like https://calendo.dev/booking/?user=<HOST_SLUG>. [L1]
  1. Action: Create the event type. Click the "+ New" button on Overview (#overviewCreateEtBtn) or "+ New Event Type" on the Event Types tab (#createEtBtn). In the form (#etForm), set Name (#etName) to CU20 Email Test <RUNID>, leave Duration (#etDuration) at 30 min, and set Description (#etDescription) to CU20 sequence + confirmation test <RUNID>. Submit the form (the form's submit button). Expect: A success toast and the new event type appears in the list with name CU20 Email Test <RUNID>. [L1]
  1. Action: Read the real slug. Open the event type's public link / copy-link control, or open the Overview booking link, and confirm the generated event slug. Record <EVENT_SLUG>. Expect: A slug derived from the name (expected cu20-email-test-<RUNID>). Use the actual observed value going forward. [L2] Capture screenshot: cu20-eventtype-created
  1. Action: Open Settings. In the sidebar click the Settings tab (a[data-tab="settings"]). Scroll to the "Email Sequences" card (heading text "Email Sequences", note the helper line "Use {{invitee_name}}, {{event_type}}, {{date}}, {{host_name}} as variables."). Expect: The Email Sequences card is visible with an "+ Add Sequence" button (#createSequenceBtn) and an (initially empty) list (#sequencesList) reading "No email sequences yet." [L1]
  1. Action: Click "+ Add Sequence" (#createSequenceBtn). The create form (#sequenceCreateForm) appears. Set Trigger (#seqTrigger) to "After booking" (value after_booking). Set Delay minutes (#seqDelay) to 0. Set Subject (#seqSubject) to CU20 seq <RUNID> for {{invitee_name}}. Set Body (#seqBody) to the body string from Test data above (the one containing {{invitee_name}}, {{event_type}}, {{date}}, {{host_name}}, {{invitee_email}}). Expect: All four fields hold the typed values. [L1] Capture screenshot: cu20-sequence-form-filled
  1. Action: Click the Create button (#seqSubmitBtn). Expect: A "Sequence created" toast; the create form hides; the sequence appears in #sequencesList as a row showing trigger "After booking", a delay column (0min), the RUNID subject, and Pause/Delete buttons. (Sequence is active by default — the button reads "Pause", meaning is_active = 1.) [L1]
  1. Action: Reload the Settings tab (full page reload of https://calendo.dev/dashboard/ then click Settings again). Confirm the sequence still lists with trigger "After booking" and the RUNID subject. Expect: The sequence persists across reload (proves it was saved via POST /api/email-sequences, not just rendered client-side). [L2] Capture screenshot: cu20-sequence-persisted
  1. Action: Note the exact UTC clock time NOW (record it; you will use it to bound the Gmail searches and to know which cron run should fire the sequence). The reminder cron runs every 5 minutes (*/5 * * * *). Expect: A recorded timestamp, e.g. booking_created_at = <UTC HH:MM>. [L1]
  1. Action: Create the booking as the RUNID invitee. Open the public booking page at https://calendo.dev/booking/?user=<HOST_SLUG>&event=<EVENT_SLUG> . Wait for the calendar (#booking-view visible). Click the first available day (.calendar-day.available); if none on the current month, click the forward nav arrow (.calendar-nav-btn — the last one) and retry (up to 6 months). When a day is selected, click the first time slot (.time-slot). Expect: The confirm form (#confirm-view) becomes visible with name/email inputs. [L1]
  1. Action: Fill invitee name (#input-name) = Invitee CU20 <RUNID> and invitee email (#input-email) = ravikantguptaofficial+inv-<RUNID>@gmail.com. Click Confirm (#btn-confirm). Expect: The confirmation screen appears: title (.confirmation-title) reads "Booking Confirmed!", and #confirmation-details contains the event name CU20 Email Test <RUNID>. [L1] Capture screenshot: cu20-booking-confirmed
  1. Action: On the confirmation screen, inspect the manage block (#confirmation-manage). Confirm it shows a Cancel link (href contains /booking/cancel.html?token=) and a Reschedule link (href contains /booking/reschedule.html?token=). Copy the cancel link token — you will need it for cleanup. Expect: Both links are present with valid ?token= values. [L2]
  1. Action: Verify the booking persisted in the dashboard. Go to https://calendo.dev/dashboard/ , click the Bookings tab (a[data-tab="bookings"]). Find the booking for Invitee CU20 <RUNID> on event CU20 Email Test <RUNID>. Expect: The booking appears with status confirmed, the RUNID invitee name/email, and the chosen date/time. [L2] Capture screenshot: cu20-booking-in-dashboard
  1. Action (L3, immediate confirmation email): Switch to the Gmail tab (https://mail.google.com). Search inv-<RUNID> (and if needed subject:(Confirmed CU20 Email Test <RUNID>)). Open the message whose subject is Confirmed: CU20 Email Test <RUNID> with <P1 host name>. Expect: The confirmation email is present (delivered within ~1-2 min of booking, sent from Calendo <notifications@calendo.dev>). Body shows Event = CU20 Email Test <RUNID>, the chosen When, Duration 30 minutes, Host = P1's name, and Reschedule/Cancel buttons. This is the immediate, non-cron email. [L3] Capture screenshot: cu20-gmail-confirmation
  1. Action (L3, sequence email — cron-gated but near-term): The after_booking delay-0 sequence fires on the NEXT */5 cron run after the booking's created_at enters the ±5-minute window. In practice this is the very next 5-minute cron boundary after step 10. Wait until at least the next 5-minute UTC boundary plus ~2 minutes has passed (worst case ~10 min after booking). Then in Gmail search subject:(CU20 seq <RUNID>). Expect: A message arrives with subject CU20 seq <RUNID> for Invitee CU20 <RUNID> — i.e. {{invitee_name}} was substituted in the SUBJECT. Open it. Verify the body reads, with all variables substituted: Hi Invitee CU20 <RUNID>, thanks for booking CU20 Email Test <RUNID> on <YYYY-MM-DD> with <P1 host name>. Reply to ravikantguptaofficial+inv-<RUNID>@gmail.com if anything changes. Confirm specifically: {{invitee_name}} -> invitee name, {{event_type}} -> event name, {{date}} -> the booking's date (YYYY-MM-DD), {{host_name}} -> P1's name, {{invitee_email}} -> the plus-alias. There must be NO literal {{...}} left anywhere in subject or body. [L3] Capture screenshot: cu20-gmail-sequence If the sequence email has not arrived after ~12 minutes: Do NOT immediately fail. Re-search once more, then record this as TIME-GATED / INCONCLUSIVE (cron may have been delayed) and hand it to manual residue — note the exact booking time and search query used so a human can re-check.
  1. Action (host notification, optional L3): In Gmail search subject:(New booking: Invitee CU20 <RUNID>). Expect: The host notification email New booking: Invitee CU20 <RUNID> - CU20 Email Test <RUNID> is present in the same inbox (host == invitee inbox here), confirming the host-side notification path also fired. [L3]
  1. Action (reminders — DOCUMENT + configure, time-gated): Reminders are independent of sequences. On the Event Types tab, open the editor for CU20 Email Test <RUNID> and locate the Reminders block (checkboxes #editEtRemEmail24, #editEtRemEmail1, #editEtRemSms24, #editEtRemSms1). Confirm Email 24h and Email 1h are checked by default. The reminder cron fires for a booking only when now is within ±5 minutes of exactly 24h (or 1h) before start_time (src/worker.js sendPendingReminders); subject will be Reminder: CU20 Email Test <RUNID> in 24 hours / ... in 1 hours (note the literal "1 hours"). Near-term trick (manual, optional): to actually observe a reminder soon, a host would book a NEW meeting whose start_time is ~1h05m in the future, then wait for the next */5 cron after the moment that is exactly 1h before that start — the 1h reminder should then arrive at both invitee and host within ~10 min. This requires an availability slot ~1h out, which production availability may not offer, so mark it as time-gated. Expect (in-run): The reminder checkboxes are present and default-on; you confirm configuration, NOT delivery, in the normal run. [L1] for configuration; reminder DELIVERY is [L3] but TIME-GATED / partly manual. Capture screenshot: cu20-reminder-settings
  1. Action (reconfirmation — DOCUMENT + configure, time-gated): Still in the event editor, locate the Reconfirmation dropdown (#editEtReconfirmation) with options None / 24h before / 48h before / 72h before. Set it to 24h before (value 24) and save the event type. Reconfirmation fires via sendPendingReconfirmations when start_time - 24h <= now < start_time and reconfirmation_sent_at IS NULL; subject Please confirm: CU20 Email Test <RUNID> with <P1 host name>, with green "Confirm Attendance" (link /api/bookings/:id/reconfirm?token=) and red "Cancel Meeting" buttons. Clicking Confirm marks reconfirmed = 1. Near-term trick (manual, optional): to observe a reconfirmation email soon, a host would book a meeting starting <24h out on an event type with reconfirmation_hours = 24; the next cron run would queue the reconfirmation email. Whether a <24h slot exists depends on availability + min-notice, so mark it as time-gated. Expect (in-run): The dropdown saves 24h before and the event type reload shows the value retained (#editEtReconfirmation = 24). [L1] / [L2] for configuration; reconfirmation DELIVERY is [L3] but TIME-GATED / partly manual. Capture screenshot: cu20-reconfirmation-setting
  1. Action: Re-open the event editor after a reload and confirm both Reminders and Reconfirmation settings persisted (#editEtReconfirmation still 24; reminder checkboxes still in their saved state). Expect: Settings survive reload (proves PUT /api/event-types/:id saved reconfirmation_hours and reminder_settings). [L2]

L3 reality checks

Perform these in the browser, in Gmail (https://mail.google.com) as ravikantguptaofficial@gmail.com:

Cleanup

Leave both accounts clean for the next run:

  1. Cancel the booking: Open the cancel link captured in step 11 (https://calendo.dev/booking/cancel.html?token=<TOKEN>), or in the dashboard Bookings tab open the Invitee CU20 <RUNID> booking and cancel it. Confirm status flips to cancelled. (This also generates a cancellation email to the same RUNID inbox — expected; it is searchable as subject:(Cancelled: CU20 Email Test <RUNID>).)
  2. Delete the email sequence: Settings tab -> Email Sequences card -> find the CU20 seq <RUNID> row in #sequencesList -> click Delete (the row's deleteSequence(...) button) -> confirm. Reload and verify it is gone.
  3. Delete the event type(s): Event Types tab -> delete CU20 Email Test <RUNID> (and CU20 Reconfirm <RUNID> if you created it). Confirm removed from the list. (Note: if the booking was not cancelled first, deletion may be blocked or orphan the booking — cancel the booking before deleting the event type.)
  4. Gmail housekeeping (optional but preferred): In Gmail, select the RUNID messages (search inv-<RUNID> and subject:(CU20 seq <RUNID>) and subject:(CU20 Email Test <RUNID>)) and archive or trash them so the host inbox stays uncluttered for the next run.
  5. Verify clean state: Re-load the dashboard; the RUNID event type, sequence, and booking must all be absent.

Pass/Fail criteria

The run PASSES only if ALL of these hold:

The run FAILS if: the sequence cannot be saved/persisted; the booking cannot be created; the immediate confirmation email never arrives (after confirming it is not a verified-domain/environment issue — if it is, FLAG as environment failure, not test failure); a delivered sequence email contains an UNsubstituted {{...}} or a wrong substitution; or any saved reminder/reconfirmation setting fails to persist.

Evidence to capture

Manual residue / cannot-verify