Этот коммит содержится в:
Harshil Sharma
2025-01-29 22:45:49 +05:30
коммит произвёл GitHub
родитель 528026d6fb
Коммит f9cff5c8d6
17 изменённых файлов: 663 добавлений и 62 удалений

Двоичные данные
e2e-tests/playwright/support/asset/archive.zip Обычный файл

Двоичный файл не отображается.

Двоичные данные
e2e-tests/playwright/support/asset/mattermost.png Обычный файл

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 75 KiB

Просмотреть файл

@@ -0,0 +1,19 @@
Lorem dolore adipisicing occaecat do qui. Laboris duis aliquip laborum ad sint. Est minim ipsum consequat. Ullamco quis magna ut anim cupidatat esse aliquip aliqua eiusmod voluptate. Aute officia aute eiusmod cillum aliquip non in elit cupidatat excepteur occaecat. Mollit elit incididunt eu dolor pariatur cillum proident id labore do Lorem officia laborum reprehenderit cupidatat. Eu nulla proident magna id dolore Lorem.
Non nisi minim mollit occaecat in culpa ullamco id dolore fugiat id eiusmod ut. Est enim commodo duis sunt fugiat. In non sunt eiusmod quis irure ullamco. Nulla eiusmod exercitation aute cillum anim.
Incididunt cillum do velit ipsum nisi enim ipsum officia non nostrud velit dolor do. Anim magna officia duis nulla occaecat labore pariatur enim. Ea sit Lorem irure adipisicing nisi aute adipisicing reprehenderit sunt cupidatat incididunt. Do magna nisi amet nostrud eiusmod. Eiusmod enim nisi dolor irure dolor dolor ipsum deserunt eiusmod veniam ipsum incididunt eu. Proident nisi duis proident proident duis velit tempor et do cillum.
Ipsum eu enim anim non excepteur quis. Proident et ea minim. Duis velit exercitation occaecat adipisicing adipisicing proident reprehenderit aliqua ea. Cillum sint anim qui eiusmod consectetur sint. Nostrud in pariatur eu proident nisi nostrud nisi et adipisicing sit. Consectetur ad consectetur ipsum sit.
In culpa irure in esse in duis consectetur amet ullamco reprehenderit sit elit culpa velit. Cillum ipsum enim officia nisi cillum adipisicing commodo anim fugiat qui quis. Excepteur aliqua adipisicing excepteur sit elit cillum velit et pariatur. Labore sint anim voluptate. Aliquip ad proident reprehenderit Lorem voluptate voluptate fugiat ea laborum ipsum.
Et proident nostrud nisi. Nisi exercitation dolor incididunt ipsum sunt consequat consequat aliquip cupidatat reprehenderit tempor. Ea excepteur sint aliqua consequat culpa proident consequat incididunt incididunt ex proident exercitation occaecat. Proident dolore dolor pariatur proident anim qui commodo enim nisi nulla anim dolore qui. Velit fugiat et commodo voluptate incididunt aliqua aute. Eiusmod anim magna commodo enim fugiat.
Eiusmod eiusmod dolore cillum tempor sit in. Cillum non ex elit velit esse exercitation amet ipsum et sunt sunt velit in ullamco. Enim sit aliquip mollit ea occaecat qui sit deserunt. Aute adipisicing sit non aliquip pariatur dolor ad minim culpa laborum consectetur fugiat.
Est incididunt exercitation consectetur occaecat veniam magna sint ea ad irure qui. Id cupidatat ut ex laboris sint anim adipisicing cillum ex in minim commodo reprehenderit duis. Cillum duis consequat occaecat et commodo ullamco exercitation sint reprehenderit deserunt dolor ipsum culpa non aute. Est cupidatat laboris proident in voluptate laborum minim officia eiusmod ipsum. Irure labore mollit esse adipisicing proident magna sit reprehenderit nisi cupidatat. Excepteur id ullamco adipisicing pariatur.
Ullamco officia et dolor consequat exercitation. Nisi aute ad aliquip nostrud deserunt nostrud. Esse reprehenderit eu cillum ullamco excepteur tempor non excepteur deserunt esse. Nisi nulla esse elit. Nulla enim consequat esse do cillum anim velit eu nulla esse amet laborum tempor occaecat. Proident voluptate exercitation cillum minim proident quis mollit mollit aliqua deserunt nostrud.
Veniam ea sit duis incididunt sint nostrud labore exercitation et dolor reprehenderit amet. Esse laborum sit veniam dolor anim amet mollit aliquip id. Laborum voluptate eiusmod consectetur. Laborum cillum voluptate enim nisi culpa ullamco cillum non aliquip nostrud do ex. Lorem elit laborum eiusmod velit id exercitation do dolor laboris et nisi et sit.

Просмотреть файл

@@ -72,6 +72,7 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
EnableOnboardingFlow: false,
EnableSecurityFixAlert: false,
GiphySdkKey: 's0glxvzVg9azvPipKxcPLpXV0q1x1fVP',
EnableTesting: true,
},
TeamSettings: {
EnableOpenServer: true,

Просмотреть файл

@@ -19,3 +19,7 @@ export async function waitForAnimationEnd(locator: Locator) {
Promise.all(element.getAnimations({subtree: true}).map((animation) => animation.finished)),
);
}
export async function moveMouseToCenter(page: Page) {
await page.mouse.move(0, 0);
}

Просмотреть файл

@@ -16,22 +16,27 @@ export default class ChannelsCenterView {
readonly postBoxIndicator;
readonly scheduledDraftChannelIcon;
readonly scheduledDraftChannelInfoMessage;
readonly scheduledDraftChannelInfoMessageLocator;
readonly scheduledDraftChannelInfoMessageText;
readonly scheduledDraftSeeAllLink;
readonly postEdit;
readonly editedPostIcon;
constructor(container: Locator) {
this.container = container;
this.scheduledDraftChannelInfoMessageLocator = 'span:has-text("Message scheduled for")';
this.header = new components.ChannelsHeader(this.container.locator('.channel-header'));
this.postCreate = new components.ChannelsPostCreate(container.getByTestId('post-create'));
this.scheduledDraftOptions = new components.ChannelsPostCreate(
container.locator('#dropdown_send_post_options'),
);
this.postEdit = new components.ChannelsPostEdit(container.locator('.post-edit__container'));
this.postBoxIndicator = container.locator('div.postBoxIndicator');
this.scheduledDraftChannelIcon = container.locator('#create_post i.icon-draft-indicator');
this.scheduledDraftChannelInfoMessage = container.locator('div.ScheduledPostIndicator span');
this.scheduledDraftChannelInfoMessageText = container.locator('span:has-text("Message scheduled for")');
this.scheduledDraftSeeAllLink = container.locator('a:has-text("See all scheduled messages")');
this.scheduledDraftChannelInfoMessageText = container.locator(this.scheduledDraftChannelInfoMessageLocator);
this.scheduledDraftSeeAllLink = container.locator('a:has-text("See all")');
this.editedPostIcon = (postID: string) => container.locator(`#postEdited_${postID}`);
}
async toBeVisible() {
@@ -65,6 +70,17 @@ export default class ChannelsCenterView {
return new components.ChannelsPost(lastPost);
}
/**
* Return the ID of the last post in the Center
*/
async getLastPostID() {
return this.container
.getByTestId('postView')
.last()
.getAttribute('id')
.then((id) => (id ? id.split('_')[1] : null));
}
/**
* Return the Nth post in the Center from the top
* @param index
@@ -115,6 +131,12 @@ export default class ChannelsCenterView {
const messageLocator = this.scheduledDraftChannelInfoMessage.first();
await expect(messageLocator).toContainText('Message scheduled for');
}
async clickOnLastEditedPost(postID: string | null) {
if (postID) {
await this.editedPostIcon(postID).click();
}
}
}
export {ChannelsCenterView};

Просмотреть файл

@@ -0,0 +1,40 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, Locator} from '@playwright/test';
export default class DeletePostConfirmationDialog {
readonly container: Locator;
readonly cancelButton;
readonly confirmButton;
constructor(container: Locator) {
this.container = container;
this.cancelButton = container.locator('button.btn.btn-tertiary');
this.confirmButton = container.locator('button#deletePostModalButton');
}
async toBeVisible() {
await expect(this.container).toBeVisible();
await expect(this.cancelButton).toBeVisible();
await expect(this.confirmButton).toBeVisible();
}
async notToBeVisible() {
await expect(this.container).not.toBeVisible();
await expect(this.cancelButton).not.toBeVisible();
await expect(this.confirmButton).not.toBeVisible();
}
async cancelDeletion() {
await this.cancelButton.click();
}
async confirmDeletion() {
await this.confirmButton.click();
}
}
export {DeletePostConfirmationDialog};

Просмотреть файл

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information.
import {expect, Locator} from '@playwright/test';
import path from 'node:path';
export default class ChannelsPostCreate {
readonly container: Locator;
@@ -23,7 +24,7 @@ export default class ChannelsPostCreate {
this.input = container.getByTestId('reply_textbox');
}
this.attachmentButton = container.getByLabel('attachment');
this.attachmentButton = container.locator('#fileUploadButton');
this.emojiButton = container.getByLabel('select an emoji');
this.sendMessageButton = container.getByTestId('SendMessageButton');
this.scheduleDraftMessageButton = container.getByLabel('Schedule message');
@@ -95,8 +96,18 @@ export default class ChannelsPostCreate {
/**
* Composes and sends a message
*/
async postMessage(message: string) {
async postMessage(message: string, files?: string[]) {
await this.writeMessage(message);
if (files) {
const filePaths = files.map((file) => path.join(path.resolve(__dirname), '../../../asset', file));
this.container.page().once('filechooser', async (fileChooser) => {
await fileChooser.setFiles(filePaths);
});
await this.attachmentButton.click();
}
await this.sendMessage();
}

Просмотреть файл

@@ -0,0 +1,94 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, Locator} from '@playwright/test';
import path from 'node:path';
import {components} from '@e2e-support/ui/components';
export default class ChannelsPostEdit {
readonly container: Locator;
readonly input;
readonly attachmentButton;
readonly emojiButton;
readonly sendMessageButton;
readonly deleteConfirmationDialog;
readonly restorePostConfirmationDialog;
constructor(container: Locator) {
this.container = container;
this.input = container.getByTestId('edit_textbox');
this.attachmentButton = container.locator('#fileUploadButton');
this.emojiButton = container.getByLabel('select an emoji');
this.sendMessageButton = container.locator('.save');
this.deleteConfirmationDialog = new components.DeletePostConfirmationDialog(
container.page().locator('#deletePostModal'),
);
this.restorePostConfirmationDialog = new components.RestorePostConfirmationDialog(
container.page().locator('#restorePostModal'),
);
}
async toBeVisible() {
await expect(this.container).toBeVisible();
await this.input.waitFor();
await expect(this.input).toBeVisible();
}
async toNotBeVisible() {
await expect(this.input).not.toBeVisible();
}
async writeMessage(message: string) {
await this.input.waitFor();
await expect(this.input).toBeVisible();
await this.input.clear();
await this.input.fill(message);
}
async addFiles(files: string[]) {
const filePaths = files.map((file) => path.join(path.resolve(__dirname), '../../../asset', file));
this.container.page().once('filechooser', async (fileChooser) => {
await fileChooser.setFiles(filePaths);
});
await this.attachmentButton.click();
}
async removeFile(fileName: string) {
const files = await this.container.locator(`.file-preview`).all();
for (let i = 0; i < files.length; i++) {
const textContent = await files[i].textContent();
if (textContent?.includes(fileName)) {
const removeButton = files[i].locator('.icon-close');
await removeButton.click();
break;
}
}
}
async sendMessage() {
await this.input.scrollIntoViewIfNeeded();
await expect(this.sendMessageButton).toBeVisible();
await expect(this.sendMessageButton).toBeEnabled();
await this.sendMessageButton.click();
}
async postMessage(message: string) {
await this.writeMessage(message);
await this.sendMessage();
}
async toContainText(text: string) {
await expect(this.container).toContainText(text);
}
}
export {ChannelsPostEdit};

Просмотреть файл

@@ -47,6 +47,13 @@ export default class PostMenu {
await this.dotMenuButton.waitFor();
await this.dotMenuButton.click();
}
/**
* Clicks on dot menu button.
*/
async clickOnDotMenu() {
await this.dotMenuButton.click();
}
}
export {PostMenu};

Просмотреть файл

@@ -0,0 +1,34 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, Locator} from '@playwright/test';
export default class RestorePostConfirmationDialog {
readonly container: Locator;
readonly cancelButton;
readonly confirmButton;
constructor(container: Locator) {
this.container = container;
this.cancelButton = container.locator('button.btn.btn-tertiary');
this.confirmButton = container.locator('button.GenericModal__button.btn.btn-primary.confirm');
}
async toBeVisible() {
await expect(this.container).toBeVisible();
await expect(this.cancelButton).toBeVisible();
await expect(this.confirmButton).toBeVisible();
}
async notToBeVisible() {
await expect(this.container).not.toBeVisible();
}
async confirmRestore() {
await this.confirmButton.click();
}
}
export {RestorePostConfirmationDialog};

Просмотреть файл

@@ -71,7 +71,7 @@ export default class ScheduledDraftModal {
*/
async selectTime() {
await this.timeLocator.click();
const timeButton = this.timeDropdownOptions.first();
const timeButton = this.timeDropdownOptions.nth(1);
await expect(timeButton).toBeVisible();
await timeButton.click();
}

Просмотреть файл

@@ -19,6 +19,10 @@ export default class ChannelsSidebarLeft {
await expect(this.container).toBeVisible();
}
async assertNoPendingScheduledDraft() {
await expect(this.scheduledDraftCountonLHS).not.toBeVisible();
}
async assertscheduledDraftCountLHS(count: string) {
await expect(this.scheduledDraftCountonLHS).toBeVisible();
await expect(this.scheduledDraftCountonLHS).toHaveText(count);

Просмотреть файл

@@ -15,17 +15,27 @@ export default class ChannelsSidebarRight {
readonly scheduledDraftChannelInfoMessage;
readonly scheduledDraftSeeAllLink;
readonly scheduledDraftChannelInfoMessageText;
readonly editTextbox;
readonly postEdit;
readonly currentVersionEditedPosttext;
readonly restorePreviousPostVersionIcon;
constructor(container: Locator) {
this.container = container;
this.postBoxIndicator = container.locator('div.postBoxIndicator');
this.scheduledDraftChannelInfoMessage = container.locator('div.ScheduledPostIndicator span');
this.scheduledDraftSeeAllLink = container.locator('a:has-text("See all scheduled messages")');
this.scheduledDraftSeeAllLink = container.locator('a:has-text("See all")');
this.scheduledDraftChannelInfoMessageText = container.locator('span:has-text("Message scheduled for")');
this.rhsPostBody = container.locator('.post-message__text');
this.postCreate = new components.ChannelsPostCreate(container.getByTestId('comment-create'), true);
this.closeButton = container.locator('#rhsCloseButton');
this.editTextbox = container.locator('#edit_textbox');
this.postEdit = new components.ChannelsPostEdit(container.locator('.post-edit__container'));
this.currentVersionEditedPosttext = (postID: any) => container.locator(`#rhsPostMessageText_${postID} p`);
this.restorePreviousPostVersionIcon = container.locator(
'button[aria-label="Select to restore an old message."]',
);
}
async toBeVisible() {
@@ -51,6 +61,12 @@ export default class ChannelsSidebarRight {
return new components.ChannelsPost(post);
}
async getFirstPost() {
const post = this.container.getByTestId('rhsPostView').first();
await post.waitFor();
return new components.ChannelsPost(post);
}
/**
* Closes the RHS
*/
@@ -65,6 +81,19 @@ export default class ChannelsSidebarRight {
await this.scheduledDraftSeeAllLink.isVisible();
await this.scheduledDraftSeeAllLink.click();
}
async toContainText(text: string) {
await expect(this.container).toContainText(text);
}
async verifyCurrentVersionPostMessage(postID: string | null, postMessageContent: string) {
expect(await this.currentVersionEditedPosttext(postID).textContent()).toBe(postMessageContent);
}
async restorePreviousPostVersion() {
await this.restorePreviousPostVersionIcon.isVisible();
await this.restorePreviousPostVersionIcon.click();
}
}
export {ChannelsSidebarRight};

Просмотреть файл

@@ -33,6 +33,9 @@ import {SystemUsers} from './system_console/sections/system_users/system_users';
import {SystemUsersFilterPopover} from './system_console/sections/system_users/filter_popover';
import {SystemUsersFilterMenu} from './system_console/sections/system_users/filter_menu';
import {SystemUsersColumnToggleMenu} from './system_console/sections/system_users/column_toggle_menu';
import ChannelsPostEdit from '@e2e-support/ui/components/channels/post_edit';
import DeletePostConfirmationDialog from '@e2e-support/ui/components/channels/delete_post_confirmation_dialog';
import RestorePostConfirmationDialog from '@e2e-support/ui/components/channels/restore_post_confirmation_dialog';
const components = {
GlobalHeader,
@@ -43,6 +46,7 @@ const components = {
ChannelsAppBar,
ChannelsHeader,
ChannelsPostCreate,
ChannelsPostEdit,
ChannelsPost,
FindChannelsModal,
DeletePostModal,
@@ -65,6 +69,8 @@ const components = {
SystemUsersColumnToggleMenu,
MessagePriority,
UserProfilePopover,
DeletePostConfirmationDialog,
RestorePostConfirmationDialog,
};
export {
@@ -76,6 +82,7 @@ export {
ChannelsAppBar,
ChannelsHeader,
ChannelsPostCreate,
ChannelsPostEdit,
ChannelsPost,
FindChannelsModal,
DeletePostModal,
@@ -83,4 +90,5 @@ export {
PostMenu,
ThreadFooter,
MessagePriority,
DeletePostConfirmationDialog,
};