summaryrefslogtreecommitdiffstats
path: root/comm/calendar/test/browser/eventDialog/browser_attendeesDialogAdd.js
blob: c1f2778118c2faf100c8d4b8db38b8d3e4c62bd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/. */

/* globals openAttendeesWindow, closeAttendeesWindow, findAndEditMatchingRow */

const { CalEvent } = ChromeUtils.import("resource:///modules/CalEvent.jsm");

add_setup(async function () {
  await CalendarTestUtils.setCalendarView(window, "day");
  CalendarTestUtils.goToDate(window, 2023, 2, 18);
});

add_task(async function testAddAttendeeToEventWithNone() {
  const calendar = CalendarTestUtils.createCalendar();
  calendar.setProperty("organizerId", "mailto:foo@example.com");
  calendar.setProperty("organizerCN", "Foo Fooson");

  // Create an event which currently has no attendees or organizer.
  const event = await calendar.addItem(
    new CalEvent(CalendarTestUtils.dedent`
      BEGIN:VEVENT
      SUMMARY:An event
      DTSTART:20230218T100000Z
      DTEND:20230218T110000Z
      END:VEVENT
    `)
  );

  // Remember event details so we can refetch it after editing.
  const eventId = event.id;
  const eventModified = event.lastModifiedTime;

  // Sanity check.
  Assert.equal(event.organizer, null, "event should not have an organizer");
  Assert.equal(event.getAttendees().length, 0, "event should not have any attendees");

  // Open our event for editing.
  const { dialogWindow: eventWindow } = await CalendarTestUtils.dayView.editEventAt(window, 1);
  const attendeesWindow = await openAttendeesWindow(eventWindow);

  // Set text in the empty row to create a new attendee.
  findAndEditMatchingRow(
    attendeesWindow,
    "bar@example.com",
    "there should an empty input",
    value => value === ""
  );

  // Save and close the event.
  await closeAttendeesWindow(attendeesWindow);
  await CalendarTestUtils.items.saveAndCloseItemDialog(eventWindow);

  await TestUtils.waitForCondition(async () => {
    const item = await calendar.getItem(eventId);
    return item.lastModifiedTime != eventModified;
  });

  const editedEvent = await calendar.getItem(eventId);

  // Verify that the organizer was set on the event.
  const organizer = editedEvent.organizer;
  Assert.ok(organizer, "there should be an organizer for the event after editing");
  Assert.equal(
    organizer.id,
    "mailto:foo@example.com",
    "organizer ID should match calendar property"
  );
  Assert.equal(organizer.commonName, "Foo Fooson", "organizer name should match calendar property");

  const attendees = editedEvent.getAttendees();
  Assert.equal(attendees.length, 2, "there should be two attendees of the event after editing");

  // Verify that the organizer was added as an attendee.
  const fooFooson = attendees.find(attendee => attendee.id == "mailto:foo@example.com");
  Assert.ok(fooFooson, "the organizer should have been added as an attendee");
  Assert.equal(fooFooson.commonName, "Foo Fooson", "attendee name should match organizer's");
  Assert.equal(
    fooFooson.participationStatus,
    "ACCEPTED",
    "organizer attendee should have automatically accepted"
  );
  Assert.equal(fooFooson.role, "REQ-PARTICIPANT", "organizer attendee should be required");

  // Verify that the attendee we added to the list is represented on the event.
  const barBarrington = attendees.find(attendee => attendee.id == "mailto:bar@example.com");
  Assert.ok(barBarrington, "an attendee should have the address bar@example.com");
  Assert.equal(barBarrington.commonName, null, "new attendee name should not be set");
  Assert.equal(
    barBarrington.participationStatus,
    "NEEDS-ACTION",
    "new attendee should have default participation status"
  );
  Assert.equal(barBarrington.role, "REQ-PARTICIPANT", "new attendee should have default role");

  CalendarTestUtils.removeCalendar(calendar);
});

add_task(async function testAddAttendeeToEventWithoutOrganizerAsAttendee() {
  const calendar = CalendarTestUtils.createCalendar();
  calendar.setProperty("organizerId", "mailto:foo@example.com");
  calendar.setProperty("organizerCN", "Foo Fooson");

  // Create an event which has an organizer and attendees, but no attendee
  // matching the organizer.
  const event = await calendar.addItem(
    new CalEvent(CalendarTestUtils.dedent`
      BEGIN:VEVENT
      SUMMARY:An event
      DTSTART:20230218T100000Z
      DTEND:20230218T110000Z
      ORGANIZER;CN="Foo Fooson":mailto:foo@example.com
      ATTENDEE;CN="Bar Barrington";PARTSTAT=DECLINED;ROLE=CHAIR:mailto:bar@examp
       le.com
      ATTENDEE;CN="Baz Luhrmann";PARTSTAT=NEEDS-ACTION;ROLE=OPT-PARTICIPANT;RSV
       P=TRUE:mailto:baz@example.com
      END:VEVENT
    `)
  );

  // Remember event details so we can refetch it after editing.
  const eventId = event.id;
  const eventModified = event.lastModifiedTime;

  // Sanity check. Note that order of attendees is not significant and thus not
  // guaranteed.
  const organizer = event.organizer;
  Assert.ok(organizer, "the organizer should be set");
  Assert.equal(organizer.id, "mailto:foo@example.com", "organizer ID should match");
  Assert.equal(organizer.commonName, "Foo Fooson", "organizer name should match");

  const attendees = event.getAttendees();
  Assert.equal(attendees.length, 2, "there should be two attendees of the event");

  const fooFooson = attendees.find(attendee => attendee.id == "mailto:foo@example.com");
  Assert.ok(!fooFooson, "there should be no attendee matching the organizer");

  const barBarrington = attendees.find(attendee => attendee.id == "mailto:bar@example.com");
  Assert.ok(barBarrington, "an attendee should have the address bar@example.com");
  Assert.equal(barBarrington.commonName, "Bar Barrington", "attendee name should match");
  Assert.equal(barBarrington.participationStatus, "DECLINED", "attendee should have declined");
  Assert.equal(barBarrington.role, "CHAIR", "attendee should be the meeting chair");

  const bazLuhrmann = attendees.find(attendee => attendee.id == "mailto:baz@example.com");
  Assert.ok(bazLuhrmann, "an attendee should have the address baz@example.com");
  Assert.equal(bazLuhrmann.commonName, "Baz Luhrmann", "attendee name should match");
  Assert.equal(
    bazLuhrmann.participationStatus,
    "NEEDS-ACTION",
    "attendee should not have responded yet"
  );
  Assert.equal(bazLuhrmann.role, "OPT-PARTICIPANT", "attendee should be optional");
  Assert.equal(bazLuhrmann.rsvp, "TRUE", "attendee should be expected to RSVP");

  // Open our event for editing.
  const { dialogWindow: eventWindow } = await CalendarTestUtils.dayView.editEventAt(window, 1);
  const attendeesWindow = await openAttendeesWindow(eventWindow);

  // Verify that we don't display an attendee for the organizer if there is no
  // attendee on the event for them.
  const attendeeList = attendeesWindow.document.getElementById("attendee-list");
  const attendeeInput = Array.from(attendeeList.children)
    .map(child => child.querySelector("input"))
    .find(input => {
      return input ? input.value.includes("foo@example.com") : false;
    });
  Assert.ok(!attendeeInput, "there should be no row in the dialog for the organizer");

  // Set text in the empty row to create a new attendee.
  findAndEditMatchingRow(
    attendeesWindow,
    "Jim James <jim@example.com>",
    "there should an empty input",
    value => value === ""
  );

  // Save and close the event.
  await closeAttendeesWindow(attendeesWindow);
  await CalendarTestUtils.items.saveAndCloseItemDialog(eventWindow);

  await TestUtils.waitForCondition(async () => {
    const item = await calendar.getItem(eventId);
    return item.lastModifiedTime != eventModified;
  });

  const editedEvent = await calendar.getItem(eventId);

  // Verify that the organizer hasn't changed.
  const editedOrganizer = editedEvent.organizer;
  Assert.ok(editedOrganizer, "the organizer should still be set on the event after editing");
  Assert.equal(
    editedOrganizer.id,
    "mailto:foo@example.com",
    "organizer ID should not have changed"
  );
  Assert.equal(editedOrganizer.commonName, "Foo Fooson", "organizer name should not have changed");

  const editedAttendees = editedEvent.getAttendees();
  Assert.equal(
    editedAttendees.length,
    3,
    "there should be three attendees of the event after editing"
  );

  // Verify that no attendee matching the organizer was added.
  const editedFooFooson = editedAttendees.find(attendee => attendee.id == "mailto:foo@example.com");
  Assert.ok(!editedFooFooson, "there should still be no attendee matching the organizer");

  // Verify that a new attendee was added.
  const jimJames = editedAttendees.find(attendee => attendee.id == "mailto:jim@example.com");
  Assert.ok(jimJames, "an attendee should have the address jim@example.com");
  Assert.equal(jimJames.commonName, "Jim James", "new attendee name should be set");
  Assert.equal(
    jimJames.participationStatus,
    "NEEDS-ACTION",
    "new attendee should have default participation status"
  );
  Assert.equal(jimJames.role, "REQ-PARTICIPANT", "new attendee should have default role");

  // Verify that the original first attendee's properties remain untouched.
  const editedBarBarrington = editedAttendees.find(
    attendee => attendee.id == "mailto:bar@example.com"
  );
  Assert.ok(editedBarBarrington, "an attendee should have the address bar@example.com");
  Assert.equal(editedBarBarrington.commonName, "Bar Barrington", "attendee name should match");
  Assert.equal(
    editedBarBarrington.participationStatus,
    "DECLINED",
    "attendee should have declined"
  );
  Assert.equal(editedBarBarrington.role, "CHAIR", "attendee should be the meeting chair");

  // Verify that the original second attendee's properties remain untouched.
  const editedBazLuhrmann = editedAttendees.find(
    attendee => attendee.id == "mailto:baz@example.com"
  );
  Assert.ok(editedBazLuhrmann, "an attendee should have the address baz@example.com");
  Assert.equal(editedBazLuhrmann.commonName, "Baz Luhrmann", "attendee name should match");
  Assert.equal(
    editedBazLuhrmann.participationStatus,
    "NEEDS-ACTION",
    "attendee should not have responded yet"
  );
  Assert.equal(editedBazLuhrmann.role, "OPT-PARTICIPANT", "attendee should be optional");
  Assert.equal(editedBazLuhrmann.rsvp, "TRUE", "attendee should be expected to RSVP");

  CalendarTestUtils.removeCalendar(calendar);
});