oficina / calendar Public

Clone
git clone https://amadan.net/oficina/calendar

Plain git — no account needed to clone.

Download

Download this file

1package calendartest
2
3import (
4 "context"
5 "net/http"
6 "strings"
7 "testing"
8 "time"
9
10 calendar "amadan.net/oficina/calendar/internal/calendar"
11)
12
13// Regressions from the code review of the booking branch.
14
15// A line break in a name would reach the mail subject, and the SMTP
16// sender refuses a folded header with an error that quotes the whole
17// subject — title, name and all — into the log (code review finding 1).
18// Refused at the form instead.
19func TestANameWithALineBreakIsRefused(t *testing.T) {
20 app, _, path, _ := publishedPage(t)
21 h := app.Handler()
22 _, starts := futureDaySlots(t, h, path)
23 rec := strangerPost(t, h, path, holdForm(starts[0], "Jane\nPrivate", "j@example.com"))
24 if rec.Code != http.StatusUnprocessableEntity || !strings.Contains(rec.Body.String(), "one line") {
25 t.Errorf("a name with a newline: %d", rec.Code)
26 }
27}
28
29// The host's confirmation carries the booker's note (spec §6); the
30// booker's mail never carries anything but their own words back.
31func TestTheHostsConfirmationCarriesTheNote(t *testing.T) {
32 app, mailer, path, _ := publishedPage(t)
33 h := app.Handler()
34 _, starts := futureDaySlots(t, h, path)
35 form := holdForm(starts[0], "Doc", "doc@tito.io")
36 form.Set("note", "Bring the folder")
37 strangerPost(t, h, path, form)
38 link := reManage.FindString(mailer.body(0))
39 strangerPost(t, h, link+"/confirm", nil)
40 if !strings.Contains(mailer.body(1), "Bring the folder") {
41 t.Errorf("the host's mail lacks the note:\n%s", mailer.body(1))
42 }
43}
44
45// The reschedule picker shows the booking's snapshotted title, not the
46// page's live one (B20).
47func TestTheReschedulePickerShowsTheSnapshot(t *testing.T) {
48 app, mailer, path, host := publishedPage(t)
49 h := app.Handler()
50 _, starts := futureDaySlots(t, h, path)
51 strangerPost(t, h, path, holdForm(starts[0], "Doc", "doc@tito.io"))
52 link := reManage.FindString(mailer.body(0))
53 strangerPost(t, h, link+"/confirm", nil)
54 st := app.StoreForTest()
55 pages, _ := st.BookingPages(context.Background(), host.ID)
56 ws, _ := calendar.ParseAvailability("every day 9-5")
57 if err := st.UpdateBookingPage(context.Background(), host.ID, pages[0].ID, calendar.BookingPageInput{
58 Title: "Renamed page", Availability: "every day 9-5", DurationMin: 30, HorizonDays: 30}, ws); err != nil {
59 t.Fatal(err)
60 }
61 body := strangerGet(t, h, link+"/reschedule").Body.String()
62 if strings.Contains(body, "Renamed page") || !strings.Contains(body, "Quick chat") {
63 t.Error("the reschedule picker shows the page's live title, not the booking's snapshot")
64 }
65}
66
67// A hold mail that is still owed when the booker confirms (the first
68// try failed, or was ambiguous) is retired unsent, not delivered as an
69// invitation to confirm what is already confirmed (B19).
70func TestAnOwedHoldMailIsRetiredOnceConfirmed(t *testing.T) {
71 t.Setenv("CARLOS_ADMIN_TOKEN", "test-token")
72 app, mailer, path, _ := publishedPage(t)
73 h := app.Handler()
74 _, starts := futureDaySlots(t, h, path)
75 mailer.refuse = "doc@tito.io"
76 strangerPost(t, h, path, holdForm(starts[0], "Doc", "doc@tito.io"))
77 mailer.refuse = ""
78 // The hold mail is owed; confirm through the store, as the booker
79 // who somehow got the link would.
80 var id int64
81 app.DBForTest().QueryRow(`SELECT id FROM bookings`).Scan(&id)
82 if _, err := app.StoreForTest().ConfirmBooking(context.Background(), id, time.Now()); err != nil {
83 t.Fatal(err)
84 }
85 app.DBForTest().Exec(`UPDATE booking_mails SET due_at = ? WHERE sent_at IS NULL`, time.Now().Add(-time.Second).Unix())
86 tick(t, h)
87 for i := 0; i < mailer.count(); i++ {
88 if strings.Contains(mailer.body(i), "confirm it here") {
89 t.Error("the drain sent a hold mail for a booking already confirmed")
90 }
91 }
92}
93