Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions playwright-tests/helpers/attachmentMenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const { expect } = require('@playwright/test');

class AttachmentMenu {
static async open(attachmentLink) {
await attachmentLink.scrollIntoViewIfNeeded();
await attachmentLink.evaluate(AttachmentMenu.waitForScrollSettled);
await attachmentLink.click();

const saveOption = attachmentLink.page().locator(
'#imageAttachmentContextMenu .context-menu-option[data-action="save"]'
);
await expect(saveOption).toBeVisible();
return saveOption;
}

// Runs in the page: allow queued scroll events and layout changes to settle
// before opening a menu that intentionally closes whenever its container scrolls.
static waitForScrollSettled(attachment) {
const container = attachment.closest('.messages-container');
if (!container) throw new Error('Attachment is not inside the message container');

return new Promise((resolve, reject) => {
let frame;
let previousPosition;
let stableSince = performance.now();
const timeout = setTimeout(() => {
cancelAnimationFrame(frame);
reject(new Error('Attachment scrolling did not settle within 5 seconds'));
}, 5_000);

const sample = (now) => {
const rect = attachment.getBoundingClientRect();
const position = [
container.scrollTop, container.scrollLeft,
rect.top, rect.left, rect.width, rect.height
].join(',');
if (position !== previousPosition) {
previousPosition = position;
stableSince = now;
}
if (now - stableSince >= 100) {
clearTimeout(timeout);
resolve();
return;
}
frame = requestAnimationFrame(sample);
};
frame = requestAnimationFrame(sample);
});
}
}

module.exports = { AttachmentMenu };
16 changes: 6 additions & 10 deletions playwright-tests/tests/attachments.e2e.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
const { test, expect } = require('../fixtures/newUserFixture');
const { createAndSignInUser, generateUsername } = require('../helpers/userHelpers');
const { newContext } = require('../helpers/toastHelpers');
const { AttachmentMenu } = require('../helpers/attachmentMenu');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

function waitForNamedDownload(page, expectedFileName) {
return page.waitForEvent('download', {

Check failure on line 10 in playwright-tests/tests/attachments.e2e.test.js

View workflow job for this annotation

GitHub Actions / e2e

[chromium] › tests/attachments.e2e.test.js:359:3 › File Attachment Tests › should verify recipient receives message and attachment and can download it

1) [chromium] › tests/attachments.e2e.test.js:359:3 › File Attachment Tests › should verify recipient receives message and attachment and can download it Error: page.waitForEvent: Target page, context or browser has been closed =========================== logs =========================== waiting for event "download" ============================================================ 8 | 9 | function waitForNamedDownload(page, expectedFileName) { > 10 | return page.waitForEvent('download', { | ^ 11 | predicate: download => download.suggestedFilename() === expectedFileName 12 | }); 13 | } at waitForNamedDownload (/home/runner/work/client-testing/client-testing/playwright-tests/tests/attachments.e2e.test.js:10:15) at /home/runner/work/client-testing/client-testing/playwright-tests/tests/attachments.e2e.test.js:403:31
predicate: download => download.suggestedFilename() === expectedFileName
});
}
Expand Down Expand Up @@ -415,7 +416,7 @@
await expect(recipientPage.locator('#chatModal')).toBeVisible();

// Verify recipient received both the message text and attachment
await expect(recipientPage.locator('.message.received .message-content', { hasText: testMessage })).toBeVisible({ timeout: 15000 });

Check failure on line 419 in playwright-tests/tests/attachments.e2e.test.js

View workflow job for this annotation

GitHub Actions / e2e

[chromium] › tests/attachments.e2e.test.js:359:3 › File Attachment Tests › should verify recipient receives message and attachment and can download it

1) [chromium] › tests/attachments.e2e.test.js:359:3 › File Attachment Tests › should verify recipient receives message and attachment and can download it Error: Timed out 15000ms waiting for expect(locator).toBeVisible() Locator: locator('.message.received .message-content').filter({ hasText: 'Message with attachment for verification' }) Expected: visible Received: <element(s) not found> Call log: - expect.toBeVisible with timeout 15000ms - waiting for locator('.message.received .message-content').filter({ hasText: 'Message with attachment for verification' }) 417 | 418 | // Verify recipient received both the message text and attachment > 419 | await expect(recipientPage.locator('.message.received .message-content', { hasText: testMessage })).toBeVisible({ timeout: 15000 }); | ^ 420 | const recipientAttachmentLink = recipientPage.locator('.message.received .attachment-label', { hasText: fileName }); 421 | await expect(recipientAttachmentLink).toBeVisible({ timeout: 15000 }); 422 | at /home/runner/work/client-testing/client-testing/playwright-tests/tests/attachments.e2e.test.js:419:107
const recipientAttachmentLink = recipientPage.locator('.message.received .attachment-label', { hasText: fileName });
await expect(recipientAttachmentLink).toBeVisible({ timeout: 15000 });

Expand Down Expand Up @@ -553,16 +554,11 @@
const attachmentLink = recipientPage.locator('.message.received .attachment-label', { hasText: attachment.fileName });
await expect(attachmentLink).toBeVisible({ timeout: 15000 });

// Set up download listener for this specific attachment
const downloadPromise = waitForNamedDownload(recipientPage, attachment.fileName);

// Click to download
await attachmentLink.click();
await expect(recipientPage.locator('#imageAttachmentContextMenu .context-menu-option[data-action="save"]')).toBeVisible();
await recipientPage.click('#imageAttachmentContextMenu .context-menu-option[data-action="save"]');

// Wait for download to start
const download = await downloadPromise;
const saveOption = await AttachmentMenu.open(attachmentLink);
const [download] = await Promise.all([
waitForNamedDownload(recipientPage, attachment.fileName),
saveOption.click(),
]);
expect(download.suggestedFilename()).toBe(attachment.fileName);

// Define path for the downloaded file with unique ID to avoid conflicts
Expand Down
Loading