summaryrefslogtreecommitdiffstats
path: root/comm/mail/test/browser/attachment/browser_attachmentEvents.js
blob: beb7034a86ff11b76a71142389cb94f211354634 (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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
/* 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/. */

/**
 * Ensures that attachment events are fired properly
 */

/* eslint-disable @microsoft/sdl/no-insecure-url */

"use strict";

var { select_attachments } = ChromeUtils.import(
  "resource://testing-common/mozmill/AttachmentHelpers.jsm"
);
var { mc } = ChromeUtils.import(
  "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
);
var utils = ChromeUtils.import("resource://testing-common/mozmill/utils.jsm");
var { add_attachments, close_compose_window, open_compose_new_mail } =
  ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
var { gMockPromptService } = ChromeUtils.import(
  "resource://testing-common/mozmill/PromptHelpers.jsm"
);

var kAttachmentsAdded = "attachments-added";
var kAttachmentsRemoved = "attachments-removed";
var kAttachmentRenamed = "attachment-renamed";

/**
 * Test that the attachments-added event is fired when we add a single
 * attachment.
 */
add_task(function test_attachments_added_on_single() {
  // Prepare to listen for attachments-added
  let eventCount = 0;
  let lastEvent;
  let listener = function (event) {
    eventCount++;
    lastEvent = event;
  };

  // Open up the compose window
  let cw = open_compose_new_mail(mc);
  cw.window.document
    .getElementById("attachmentBucket")
    .addEventListener(kAttachmentsAdded, listener);

  // Attach a single file
  add_attachments(cw, "http://www.example.com/1", 0, false);

  // Make sure we only saw the event once
  Assert.equal(1, eventCount);

  // Make sure that we were passed the right subject
  let subjects = lastEvent.detail;
  Assert.equal(1, subjects.length);
  Assert.equal("http://www.example.com/1", subjects[0].url);

  // Make sure that we can get that event again if we
  // attach more files.
  add_attachments(cw, "http://www.example.com/2", 0, false);
  Assert.equal(2, eventCount);
  subjects = lastEvent.detail;
  Assert.equal("http://www.example.com/2", subjects[0].url);

  // And check that we don't receive the event if we try to attach a file
  // that's already attached.
  add_attachments(cw, "http://www.example.com/2", null, false);
  Assert.equal(2, eventCount);

  cw.window.document
    .getElementById("attachmentBucket")
    .removeEventListener(kAttachmentsAdded, listener);
  close_compose_window(cw);
});

/**
 * Test that the attachments-added event is fired when we add a series
 * of files all at once.
 */
add_task(function test_attachments_added_on_multiple() {
  // Prepare to listen for attachments-added
  let eventCount = 0;
  let lastEvent;
  let listener = function (event) {
    eventCount++;
    lastEvent = event;
  };

  // Prepare the attachments - we store the names in attachmentNames to
  // make sure that we observed the right event subjects later on.
  let attachmentUrls = ["http://www.example.com/1", "http://www.example.com/2"];

  // Open the compose window and add the attachments
  let cw = open_compose_new_mail(mc);
  cw.window.document
    .getElementById("attachmentBucket")
    .addEventListener(kAttachmentsAdded, listener);

  add_attachments(cw, attachmentUrls, null, false);

  // Make sure we only saw a single attachments-added for this group
  // of files.
  Assert.equal(1, eventCount);

  // Now make sure we got passed the right subjects for the event
  let subjects = lastEvent.detail;
  Assert.equal(2, subjects.length);

  for (let attachment of subjects) {
    Assert.ok(attachmentUrls.includes(attachment.url));
  }

  // Close the compose window - let's try again with 3 attachments.
  cw.window.document
    .getElementById("attachmentBucket")
    .removeEventListener(kAttachmentsAdded, listener);
  close_compose_window(cw);

  attachmentUrls = [
    "http://www.example.com/1",
    "http://www.example.com/2",
    "http://www.example.com/3",
  ];

  // Open the compose window and attach the files, and ensure that we saw
  // the attachments-added event
  cw = open_compose_new_mail(mc);
  cw.window.document
    .getElementById("attachmentBucket")
    .addEventListener(kAttachmentsAdded, listener);

  add_attachments(cw, attachmentUrls, null, false);
  Assert.equal(2, eventCount);

  // Make sure that we got the right subjects back
  subjects = lastEvent.detail;
  Assert.equal(3, subjects.length);

  for (let attachment of subjects) {
    Assert.ok(attachmentUrls.includes(attachment.url));
  }

  // Make sure we don't fire the event again if we try to attach the same
  // files.
  add_attachments(cw, attachmentUrls, null, false);
  Assert.equal(2, eventCount);

  cw.window.document
    .getElementById("attachmentBucket")
    .removeEventListener(kAttachmentsAdded, listener);
  close_compose_window(cw);
});

/**
 * Test that the attachments-removed event is fired when removing a
 * single file.
 */
add_task(function test_attachments_removed_on_single() {
  // Prepare to listen for attachments-removed
  let eventCount = 0;
  let lastEvent;
  let listener = function (event) {
    eventCount++;
    lastEvent = event;
  };

  // Open up the compose window, attach a file...
  let cw = open_compose_new_mail(mc);
  cw.window.document
    .getElementById("attachmentBucket")
    .addEventListener(kAttachmentsRemoved, listener);

  add_attachments(cw, "http://www.example.com/1");

  // Now select that attachment and delete it
  select_attachments(cw, 0);
  // We need to hold a reference to removedAttachment here because
  // the delete routine nulls it out from the attachmentitem.
  cw.window.goDoCommand("cmd_delete");
  // Make sure we saw the event
  Assert.equal(1, eventCount);
  // And make sure we were passed the right attachment item as the
  // subject.
  let subjects = lastEvent.detail;
  Assert.equal(1, subjects.length);
  Assert.equal(subjects[0].url, "http://www.example.com/1");

  // Ok, let's attach it again, and remove it again to ensure that
  // we still see the event.
  add_attachments(cw, "http://www.example.com/2");
  select_attachments(cw, 0);
  cw.window.goDoCommand("cmd_delete");

  Assert.equal(2, eventCount);
  subjects = lastEvent.detail;
  Assert.equal(1, subjects.length);
  Assert.equal(subjects[0].url, "http://www.example.com/2");

  cw.window.document
    .getElementById("attachmentBucket")
    .removeEventListener(kAttachmentsRemoved, listener);
  close_compose_window(cw);
});

/**
 * Test that the attachments-removed event is fired when removing multiple
 * files all at once.
 */
add_task(function test_attachments_removed_on_multiple() {
  // Prepare to listen for attachments-removed
  let eventCount = 0;
  let lastEvent;
  let listener = function (event) {
    eventCount++;
    lastEvent = event;
  };

  // Open up the compose window and attach some files...
  let cw = open_compose_new_mail(mc);
  cw.window.document
    .getElementById("attachmentBucket")
    .addEventListener(kAttachmentsRemoved, listener);

  add_attachments(cw, [
    "http://www.example.com/1",
    "http://www.example.com/2",
    "http://www.example.com/3",
  ]);

  // Select all three attachments, and remove them.
  let removedAttachmentItems = select_attachments(cw, 0, 2);

  let removedAttachmentUrls = removedAttachmentItems.map(
    aAttachment => aAttachment.attachment.url
  );

  cw.window.goDoCommand("cmd_delete");

  // We should have seen the attachments-removed event exactly once.
  Assert.equal(1, eventCount);

  // Now let's make sure we got passed back the right attachment items
  // as the event subject
  let subjects = lastEvent.detail;
  Assert.equal(3, subjects.length);

  for (let attachment of subjects) {
    Assert.ok(removedAttachmentUrls.includes(attachment.url));
  }

  // Ok, let's attach and remove some again to ensure that we still see the event.
  add_attachments(cw, ["http://www.example.com/1", "http://www.example.com/2"]);

  select_attachments(cw, 0, 1);
  cw.window.goDoCommand("cmd_delete");
  Assert.equal(2, eventCount);

  cw.window.document
    .getElementById("attachmentBucket")
    .removeEventListener(kAttachmentsRemoved, listener);
  close_compose_window(cw);
});

/**
 * Test that we don't see the attachments-removed event if no attachments
 * are selected when hitting "Delete"
 */
add_task(function test_no_attachments_removed_on_none() {
  // Prepare to listen for attachments-removed
  let eventCount = 0;
  let listener = function (event) {
    eventCount++;
  };

  // Open the compose window and add some attachments.
  let cw = open_compose_new_mail(mc);
  cw.window.document
    .getElementById("attachmentBucket")
    .addEventListener(kAttachmentsRemoved, listener);

  add_attachments(cw, [
    "http://www.example.com/1",
    "http://www.example.com/2",
    "http://www.example.com/3",
  ]);

  // Choose no attachments
  cw.window.document.getElementById("attachmentBucket").clearSelection();
  // Run the delete command
  cw.window.goDoCommand("cmd_delete");
  // Make sure we didn't see the attachments_removed event.
  Assert.equal(0, eventCount);
  cw.window.document
    .getElementById("attachmentBucket")
    .removeEventListener(kAttachmentsRemoved, listener);

  close_compose_window(cw);
});

/**
 * Test that we see the attachment-renamed event when an attachments
 * name is changed.
 */
add_task(function test_attachment_renamed() {
  // Here's what we'll rename some files to.
  const kRenameTo1 = "Renamed-1";
  const kRenameTo2 = "Renamed-2";
  const kRenameTo3 = "Renamed-3";

  // Prepare to listen for attachment-renamed
  let eventCount = 0;
  let lastEvent;
  let listener = function (event) {
    eventCount++;
    lastEvent = event;
  };

  // Renaming a file brings up a Prompt, so we'll mock the Prompt Service
  gMockPromptService.reset();
  gMockPromptService.register();
  // The inoutValue is used to set the attachment name
  gMockPromptService.inoutValue = kRenameTo1;
  gMockPromptService.returnValue = true;

  // Open up the compose window, attach some files, choose the first
  // attachment, and choose to rename it.
  let cw = open_compose_new_mail(mc);
  cw.window.document
    .getElementById("attachmentBucket")
    .addEventListener(kAttachmentRenamed, listener);

  add_attachments(cw, [
    "http://www.example.com/1",
    "http://www.example.com/2",
    "http://www.example.com/3",
  ]);

  select_attachments(cw, 0);
  Assert.equal(0, eventCount);
  cw.window.goDoCommand("cmd_renameAttachment");

  // Wait until we saw the attachment-renamed event.
  utils.waitFor(function () {
    return eventCount == 1;
  });

  // Ensure that the event mentions the right attachment
  let renamedAttachment1 = lastEvent.target.attachment;
  let originalAttachment1 = lastEvent.detail;
  Assert.ok(renamedAttachment1 instanceof Ci.nsIMsgAttachment);
  Assert.equal(kRenameTo1, renamedAttachment1.name);
  Assert.ok(renamedAttachment1.url.includes("http://www.example.com/1"));
  Assert.equal("www.example.com/1", originalAttachment1.name);

  // Ok, let's try renaming the same attachment.
  gMockPromptService.reset();
  gMockPromptService.inoutValue = kRenameTo2;
  gMockPromptService.returnValue = true;

  select_attachments(cw, 0);
  Assert.equal(1, eventCount);
  cw.window.goDoCommand("cmd_renameAttachment");

  // Wait until we saw the attachment-renamed event.
  utils.waitFor(function () {
    return eventCount == 2;
  });

  let renamedAttachment2 = lastEvent.target.attachment;
  let originalAttachment2 = lastEvent.detail;
  Assert.ok(renamedAttachment2 instanceof Ci.nsIMsgAttachment);
  Assert.equal(kRenameTo2, renamedAttachment2.name);
  Assert.ok(renamedAttachment2.url.includes("http://www.example.com/1"));
  Assert.equal(kRenameTo1, originalAttachment2.name);

  // Ok, let's rename another attachment
  gMockPromptService.reset();
  gMockPromptService.inoutValue = kRenameTo3;
  gMockPromptService.returnValue = true;

  // We'll select the second attachment this time.
  select_attachments(cw, 1);
  Assert.equal(2, eventCount);
  cw.window.goDoCommand("cmd_renameAttachment");

  // Wait until we saw the attachment-renamed event.
  utils.waitFor(function () {
    return eventCount == 3;
  });

  // Ensure that the event mentions the right attachment
  let renamedAttachment3 = lastEvent.target.attachment;
  let originalAttachment3 = lastEvent.detail;
  Assert.ok(renamedAttachment3 instanceof Ci.nsIMsgAttachment);
  Assert.equal(kRenameTo3, renamedAttachment3.name);
  Assert.ok(renamedAttachment3.url.includes("http://www.example.com/2"));
  Assert.equal("www.example.com/2", originalAttachment3.name);

  // Unregister the Mock Prompt service, and remove our observer.
  cw.window.document
    .getElementById("attachmentBucket")
    .removeEventListener(kAttachmentRenamed, listener);

  close_compose_window(cw);
  gMockPromptService.unregister();
});

/**
 * Test that the attachment-renamed event is not fired if we set the
 * filename to be blank.
 */
add_task(function test_no_attachment_renamed_on_blank() {
  // Prepare to listen for attachment-renamed
  let eventCount = 0;
  let listener = function (event) {
    eventCount++;
  };

  // Register the Mock Prompt Service to return the empty string when
  // prompted.
  gMockPromptService.reset();
  gMockPromptService.register();
  gMockPromptService.inoutValue = "";
  gMockPromptService.returnValue = true;

  // Open the compose window, attach some files, select one, and chooes to
  // rename it.
  let cw = open_compose_new_mail(mc);
  cw.window.document
    .getElementById("attachmentBucket")
    .addEventListener(kAttachmentRenamed, listener);

  add_attachments(cw, [
    "http://www.example.com/1",
    "http://www.example.com/2",
    "http://www.example.com/3",
  ]);

  select_attachments(cw, 0);
  cw.window.goDoCommand("cmd_renameAttachment");

  // Ensure that we didn't see the attachment-renamed event.
  Assert.equal(0, eventCount);
  cw.window.document
    .getElementById("attachmentBucket")
    .removeEventListener(kAttachmentRenamed, listener);
  close_compose_window(cw);
  gMockPromptService.unregister();
});

/**
 * Test that toggling attachments pane works.
 */
add_task(function test_attachments_pane_toggle() {
  // Open the compose window.
  let cw = open_compose_new_mail(mc);

  // Use the hotkey to try to toggle attachmentsArea open.
  let opts =
    AppConstants.platform == "macosx"
      ? { metaKey: true, shiftKey: true }
      : { ctrlKey: true, shiftKey: true };
  EventUtils.synthesizeKey("m", opts, cw.window);
  let attachmentArea = cw.window.document.getElementById("attachmentArea");

  // Since we don't have any uploaded attachment, assert that the box remains
  // closed.
  utils.waitFor(() => !attachmentArea.open);
  Assert.ok(!attachmentArea.open);

  // Add an attachment. This should automatically open the box.
  add_attachments(cw, ["http://www.example.com/1"]);
  Assert.ok(attachmentArea.open);

  // Press again, should toggle to closed.
  EventUtils.synthesizeKey("m", opts, cw.window);
  utils.waitFor(() => !attachmentArea.open);
  Assert.ok(!attachmentArea.open);

  // Press again, should toggle to open.
  EventUtils.synthesizeKey("m", opts, cw.window);
  utils.waitFor(() => attachmentArea.open);
  Assert.ok(attachmentArea.open);

  close_compose_window(cw);
});

registerCleanupFunction(() => {
  // Some tests that open new windows don't return focus to the main window
  // in a way that satisfies mochitest, and the test times out.
  Services.focus.focusedWindow = window;
});