* Migrate feature/wrangler to mono-repo

* Add wrangler files

* Fix linters, types, etc

* Fix snapshots

* Fix playwright

* Fix pipelines

* Fix more pipeline

* Fixes for pipelines

* More changes for pipeline

* Fix types

* Add support for a feature flag, but leave it defaulted on for spinwick usage for now

* Update snapshot

* fix js error when removing last value of multiselect, support CSV marshaling to string array for textsetting

* Fix linter

* Remove TODO

* Remove another TODO

* fix tests

* Fix i18n

* Add server tests

* Fix linter

* Fix linter

* Use proper icon for dot menu

* Update snapshot

* Add Cypress UI tests for various entrypoints to move thread modal, split SCSS out from forward post into its own thing

* clean up

* fix linter

* More cleanup

* Revert files to master

* Fix linter for e2e tests

* Make ForwardPostChannelSelect channel types configurable with a prop

* Add missing return

* Fixes from PR feedback

* First batch of PR Feedback

* Another batch of PR changes

* Fix linter

* Update snapshots

* Wrangler system messages are translated to each user's locale

* Initially translate Wrangler into system locale rather than initiating user

* More fixes for PR Feedback

* Fix some server tests

* More updates with master. Fixes around pipelines. Enforce Enterprise license on front/back end

* Add tests for dot_menu

* More pipeline fixes

* Fix e2etests prettier

* Update cypress tests, change occurrences of 'Wrangler' with 'Move Thread'

* Fix linter

* Remove enterprise lock

* A couple more occurrences of wrangler strings, and one more enterprise lock

* Fix server tests

* Fix i18n

* Fix e2e linter

* Feature flag shouldn't be on by default

* Enable move threads feature in smoke tests (#25657)

* enable move threads feature
* add @prod tag

* Fix move_thread_from_public_channel e2e test

* Fix e2e style

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com>
Этот коммит содержится в:
Nick Misasi
2023-12-11 15:27:34 -05:00
коммит произвёл GitHub
родитель bfb8320afd
Коммит f0a336ba07
56 изменённых файлов: 3107 добавлений и 16 удалений

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

@@ -66,6 +66,7 @@ services:
MM_SERVICESETTINGS_ENABLEONBOARDINGFLOW: "false"
MM_FEATUREFLAGS_ONBOARDINGTOURTIPS: "false"
MM_SERVICEENVIRONMENT: "test"
MM_FEATUREFLAGS_MOVETHREADSENABLED: "true"
network_mode: host
depends_on:
$(for service in $ENABLED_DOCKER_SERVICES; do

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

@@ -0,0 +1,213 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @messaging
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Move Thread', () => {
let user1;
let user2;
let testTeam;
let dmChannel;
let testPost;
let replyPost;
const message = 'Move this message';
const replyMessage = 'Move this reply';
beforeEach(() => {
cy.shouldHaveFeatureFlag('MoveThreadsEnabled', true);
cy.apiUpdateConfig({
ServiceSettings: {
ThreadAutoFollow: true,
CollapsedThreads: 'default_on',
},
WranglerSettings: {
MoveThreadFromDirectMessageChannelEnable: true,
},
});
// # Login as new user, create new team and visit its URL
cy.apiInitSetup({loginAfter: true, promoteNewUserAsAdmin: true}).then(({
user,
team,
}) => {
user1 = user;
testTeam = team;
// # enable CRT for the user
cy.apiSaveCRTPreference(user.id, 'on');
// # Create another user
return cy.apiCreateUser({prefix: 'second_'});
}).then(({user}) => {
user2 = user;
// # Add other user to team
return cy.apiAddUserToTeam(testTeam.id, user2.id);
}).then(() => {
// # Create new DM channel
return cy.apiCreateDirectChannel([user1.id, user2.id]);
}).then(({channel}) => {
dmChannel = channel;
// # Post a sample message
return cy.postMessageAs({sender: user1, message, channelId: dmChannel.id});
}).then((post) => {
testPost = post.data;
// # Post a reply
return cy.postMessageAs({sender: user1, message: replyMessage, channelId: dmChannel.id, rootId: testPost.id});
}).then((post) => {
replyPost = post.data;
// # Got to Test channel
cy.visit(`/${testTeam.name}/channels/${dmChannel.name}`);
});
});
afterEach(() => {
// # Go to 1. public channel
cy.visit(`/${testTeam.name}/channels/${dmChannel.name}`);
});
it('Move root post from DM', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').type('{shift}W');
// # move thread
movePostFromDM();
// * Assert switch to DM channel
cy.get('#channelHeaderTitle', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').should('contain', dmChannel.display_name);
// * Assert post has been moved
verifyMovedThread({post: testPost});
});
it('Move thread reply from DM', () => {
// # Open the RHS with replies to the root post
cy.uiClickPostDropdownMenu(testPost.id, 'Reply', 'CENTER');
// * Assert RHS is open
cy.get('#rhsContainer').should('be.visible');
// # Click on ... button of reply post
cy.clickPostDotMenu(replyPost.id, 'RHS_COMMENT');
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').type('{shift}W');
// # move thread
movePostFromDM();
// * Assert switch to DM channel
cy.get('#channelHeaderTitle', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').should('contain', dmChannel.display_name);
// * Assert post has been moved
verifyMovedThread({post: testPost});
});
it('Move post from DM - Cancel using escape key', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').type('{shift}W');
// # move thread
movePostFromDM({cancel: true});
// * Assert still in the DM channel
cy.get('#channelHeaderTitle', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').should('contain', dmChannel.display_name);
// * Assert last post id is identical with testPost
cy.getLastPostId((id) => {
assert.isEqual(id, testPost.id);
});
});
it('Should not be able to move post from DM if configured off', () => {
cy.apiUpdateConfig({
WranglerSettings: {
MoveThreadFromDirectMessageChannelEnable: false,
},
});
// # Open the RHS with replies to the root post
cy.uiClickPostDropdownMenu(testPost.id, 'Reply', 'CENTER');
// * Assert RHS is open
cy.get('#rhsContainer').should('be.visible');
// # Click on ... button of reply post
cy.clickPostDotMenu(replyPost.id, 'RHS_COMMENT');
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').should('not.exist');
});
/**
* Verify that the post has been moved
*
* @param {Post} post
*/
const verifyMovedThread = ({post}) => {
// * Assert post has been moved
cy.getLastPostId().then((id) => {
// * Assert last post is visible
cy.get(`#${id}_message`).should('be.visible').within(() => {
// * Assert the text in the preview matches the original post message
cy.get(`#postMessageText_${post.id}`).should('be.visible').should('contain.text', post.message);
});
// # Cleanup
cy.apiDeletePost(id);
});
};
/**
* move thread
*
* @param {object?} options
* @param {boolean?} options.cancel
*/
const movePostFromDM = ({cancel = false} = {}) => {
// * Assert visibility of the move thread modal
cy.get('#move-thread-modal').should('be.visible').within(() => {
// * Assert channel select is not existent
cy.get('.move-thread__select').should('not.exist');
// * Assert if button is enabled
cy.get('.GenericModal__button.confirm').should('not.be.disabled');
// * Assert Notification is shown
cy.findByTestId('notification-text').should('be.visible').should('contain.text', 'Moving this thread changes who has access');
if (cancel) {
// * Assert if button is active
cy.get('.MoveThreadModal__cancel-button').should('not.be.disabled').type('{esc}', {force: true});
} else {
// * Assert if button is active
cy.get('.GenericModal__button.confirm').should('not.be.disabled').type('{enter}', {force: true});
}
});
};
});

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

@@ -0,0 +1,238 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @messaging
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Move thread', () => {
let user1;
let user2;
let user3;
let testTeam;
let gmChannel;
let gmChannelName;
let testPost;
let replyPost;
const message = 'Move this message';
const replyMessage = 'Move this reply';
beforeEach(() => {
cy.shouldHaveFeatureFlag('MoveThreadsEnabled', true);
cy.apiUpdateConfig({
ServiceSettings: {
ThreadAutoFollow: true,
CollapsedThreads: 'default_on',
},
WranglerSettings: {
MoveThreadFromGroupMessageChannelEnable: true,
},
});
// # Login as new user, create new team and visit its URL
cy.apiInitSetup({loginAfter: true, promoteNewUserAsAdmin: true}).then(({
user,
team,
}) => {
user1 = user;
testTeam = team;
// # enable CRT for the user
cy.apiSaveCRTPreference(user.id, 'on');
// # Create another user
return cy.apiCreateUser({prefix: 'second_'});
}).then(({user}) => {
user2 = user;
// # Add other user to team
return cy.apiAddUserToTeam(testTeam.id, user2.id);
}).then(() => {
// # Create another user
return cy.apiCreateUser({prefix: 'third_'});
}).then(({user}) => {
user3 = user;
// # Add other user to team
return cy.apiAddUserToTeam(testTeam.id, user3.id);
}).then(() => {
// # Create new GM channel
return cy.apiCreateGroupChannel([user1.id, user2.id, user3.id]);
}).then(({channel}) => {
gmChannel = channel;
gmChannelName = gmChannel.display_name.split(', ').filter(((username) => username !== user1.username)).join(', ');
// # Post a sample message
return cy.postMessageAs({sender: user1, message, channelId: gmChannel.id});
}).then((post) => {
testPost = post.data;
// # Post a reply
return cy.postMessageAs({sender: user1, message: replyMessage, channelId: gmChannel.id, rootId: testPost.id});
}).then((post) => {
replyPost = post.data;
// # Got to Test channel
cy.visit(`/${testTeam.name}/channels/${gmChannel.name}`);
});
});
afterEach(() => {
// # Go to 1. public channel
cy.visit(`/${testTeam.name}/channels/${gmChannel.name}`);
});
it('Move post from GM (with at least 2 other users)', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move menu-item
cy.findByText('Move Thread').type('{shift}W');
// # Move Post
moveThreadFromGM();
// * Assert switch to GM channel
cy.get('#channelHeaderTitle', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').should('contain', gmChannelName);
// * Assert post has been moved
verifyMovedMessage({post: testPost});
});
it('Move thread with replies from GM (with at least 2 other users)', () => {
// # Open the RHS with replies to the root post
cy.uiClickPostDropdownMenu(testPost.id, 'Reply', 'CENTER');
// * Assert RHS is open
cy.get('#rhsContainer').should('be.visible');
// # Click on ... button of reply post
cy.clickPostDotMenu(replyPost.id, 'RHS_COMMENT');
// * Assert availability of the Move menu-item
cy.findByText('Move Thread').type('{shift}W');
// # Move Post
moveThreadFromGM();
// * Assert switch to GM channel
cy.get('#channelHeaderTitle', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').should('contain', gmChannelName);
// * Assert post has been moved
verifyMovedMessage({post: testPost});
});
it('Move thread from GM (with at least 2 other users) - Cancel using X', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move menu-item
cy.findByText('Move Thread').type('{shift}W');
// # Move Post
moveThreadFromGM({cancel: true});
// * Assert switch to GM channel
cy.get('#channelHeaderTitle', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').should('contain', gmChannelName);
// * Assert last post id is identical with testPost
cy.getLastPostId((id) => {
assert.isEqual(id, testPost.id);
});
});
it('Should not be able to move post from GM if configured off', () => {
cy.apiUpdateConfig({
WranglerSettings: {
MoveThreadFromGroupMessageChannelEnable: false,
},
});
// # Open the RHS with replies to the root post
cy.uiClickPostDropdownMenu(testPost.id, 'Reply', 'CENTER');
// * Assert RHS is open
cy.get('#rhsContainer').should('be.visible');
// # Click on ... button of reply post
cy.clickPostDotMenu(replyPost.id, 'RHS_COMMENT');
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').should('not.exist');
});
/**
* Verify that the post has been moved
*
* @param {string?} comment
* @param {boolean?} showMore
* @param {Post} post
*/
const verifyMovedMessage = ({post, comment, showMore}) => {
const permaLink = `${Cypress.config('baseUrl')}/${testTeam.name}/pl/${post.id}`;
// * Assert post has been moved
cy.getLastPostId().then((id) => {
// * Assert last post is visible
cy.get(`#${id}_message`).should('be.visible').within(() => {
if (comment) {
// * Assert the text in the post body is the permalink only
cy.get(`#postMessageText_${id}`).should('be.visible').should('contain.text', permaLink).should('contain.text', comment);
if (showMore) {
// * Assert show more button is rendered and works as expected
cy.get('#showMoreButton').should('be.visible').should('contain.text', 'Show more').click().should('contain.text', 'Show less').click();
}
}
// * Assert the text in the preview matches the original post message
cy.get(`#postMessageText_${post.id}`).should('be.visible').should('contain.text', post.message);
});
// # Cleanup
cy.apiDeletePost(id);
});
};
/**
* Move thread
*
* @param {object?} options
* @param {boolean?} options.cancel
*/
const moveThreadFromGM = ({cancel = false} = {}) => {
// * Assert visibility of the move thread modal
cy.get('#move-thread-modal').should('be.visible').within(() => {
// * Assert channel select is not existent
cy.get('.move-thread__select').should('not.exist');
// * Assert if button is enabled
cy.get('.GenericModal__button.confirm').should('not.be.disabled');
// * Assert Notification is shown
cy.findByTestId('notification-text').should('be.visible').should('contain.text', 'Moving this thread changes who has access');
if (cancel) {
// * Assert if button is active
cy.uiCloseModal('Move thread');
} else {
// * Assert if button is active
cy.get('.GenericModal__button.confirm').should('not.be.disabled').type('{enter}', {force: true});
}
});
};
});

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

@@ -0,0 +1,199 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @messaging
import * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Move thread', () => {
let user1;
let testTeam;
let privateChannel;
let testPost;
let replyPost;
const message = 'Move this message';
const replyMessage = 'Move this reply';
beforeEach(() => {
cy.apiRequireLicense();
cy.apiUpdateConfig({
ServiceSettings: {
ThreadAutoFollow: true,
CollapsedThreads: 'default_on',
},
WranglerSettings: {
MoveThreadFromPrivateChannelEnable: true,
},
});
// # Login as new user, create new team and visit its URL
cy.apiInitSetup({loginAfter: true, promoteNewUserAsAdmin: true}).then(({
user,
team,
}) => {
user1 = user;
testTeam = team;
// # enable CRT for the user
cy.apiSaveCRTPreference(user.id, 'on');
// # Create a private channel
return cy.apiCreateChannel(testTeam.id, 'private', 'Private', 'P');
}).then(({channel}) => {
privateChannel = channel;
// # Post a sample message
return cy.postMessageAs({sender: user1, message, channelId: privateChannel.id});
}).then((post) => {
testPost = post.data;
// # Post a reply
return cy.postMessageAs({sender: user1, message: replyMessage, channelId: privateChannel.id, rootId: testPost.id});
}).then((post) => {
replyPost = post.data;
// # Got to Private channel
cy.visit(`/${testTeam.name}/channels/${privateChannel.name}`);
});
});
it('Move root post from private channel', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').type('{shift}W');
// # Move Thread
moveThreadFromPrivateChannel();
// * Assert switch to testchannel
cy.get('#channelHeaderTitle', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').should('contain', privateChannel.display_name);
// * Assert post has been moved
verifyMovedMessage({post: testPost});
});
it('Move thread with replies from private channel', () => {
// # Open the RHS with replies to the root post
cy.uiClickPostDropdownMenu(testPost.id, 'Reply', 'CENTER');
// * Assert RHS is open
cy.get('#rhsContainer').should('be.visible');
// # Click on ... button of reply post
cy.clickPostDotMenu(replyPost.id, 'RHS_COMMENT');
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').type('{shift}W');
// # Move Thread
moveThreadFromPrivateChannel();
// * Assert switch to testchannel
cy.get('#channelHeaderTitle', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').should('contain', privateChannel.display_name);
// * Assert post has been moved
verifyMovedMessage({post: testPost});
});
it('Move post from private channel - Cancel', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').type('{shift}W');
// # Move Thread
moveThreadFromPrivateChannel(true);
// * Assert switch to testchannel
cy.get('#channelHeaderTitle', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible').should('contain', privateChannel.display_name);
// * Assert last post id is identical with testPost
cy.getLastPostId((id) => {
assert.isEqual(id, testPost.id);
});
});
it('Should not be able to move post from private channel if configured off', () => {
cy.apiUpdateConfig({
WranglerSettings: {
MoveThreadFromPrivateChannelEnable: false,
},
});
// # Open the RHS with replies to the root post
cy.uiClickPostDropdownMenu(testPost.id, 'Reply', 'CENTER');
// * Assert RHS is open
cy.get('#rhsContainer').should('be.visible');
// # Click on ... button of reply post
cy.clickPostDotMenu(replyPost.id, 'RHS_COMMENT');
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').should('not.exist');
});
/**
* Verify that the post has been moved
*
* @param {Post} post
*/
const verifyMovedMessage = ({post}) => {
// * Assert post has been moved
cy.getLastPostId().then((id) => {
// * Assert last post is visible
cy.get(`#${id}_message`).should('be.visible').within(() => {
// * Assert the text in the preview matches the original post message
cy.get(`#postMessageText_${post.id}`).should('be.visible').should('contain.text', post.message);
});
// # Cleanup
cy.apiDeletePost(id);
});
};
/**
* Move thread
*
* @param {boolean?} cancel
*/
const moveThreadFromPrivateChannel = (cancel = false) => {
// * Assert visibility of the move thread modal
cy.get('#move-thread-modal').should('be.visible').within(() => {
// * Assert channel select is not existent
cy.get('.move-thread__select').should('not.exist');
// * Assert if button is enabled
cy.get('.GenericModal__button.confirm').should('not.be.disabled');
// * Assert Notification is shown
cy.findByTestId('notification-text').should('be.visible').should('contain.text', 'Moving this thread changes who has access');
if (cancel) {
// * Assert if button is active
cy.get('.MoveThreadModal__cancel-button').should('not.be.disabled').click();
} else {
// * Assert if button is active
cy.get('.GenericModal__button.confirm').should('not.be.disabled').click();
}
});
};
});

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

@@ -0,0 +1,230 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @messaging
describe('Move Thread', () => {
let user1;
let user2;
let user3;
let testTeam;
let testChannel;
let otherChannel;
let privateChannel;
let dmChannel;
let gmChannel;
let testPost;
let replyPost;
const message = 'Move this message';
const replyMessage = 'Move this reply';
beforeEach(() => {
cy.apiUpdateConfig({
ServiceSettings: {
ThreadAutoFollow: true,
CollapsedThreads: 'default_on',
},
});
// # Login as new user, create new team and visit its URL
cy.apiInitSetup({loginAfter: true, promoteNewUserAsAdmin: true}).then(({
user,
team,
channel,
}) => {
user1 = user;
testTeam = team;
testChannel = channel;
// # enable CRT for the user
cy.apiSaveCRTPreference(user.id, 'on');
// # Create another user
return cy.apiCreateUser({prefix: 'second_'});
}).then(({user}) => {
user2 = user;
// # Add other user to team
return cy.apiAddUserToTeam(testTeam.id, user2.id);
}).then(() => {
// # Create another user
return cy.apiCreateUser({prefix: 'third_'});
}).then(({user}) => {
user3 = user;
// # Add other user to team
return cy.apiAddUserToTeam(testTeam.id, user3.id);
}).then(() => {
cy.apiAddUserToChannel(testChannel.id, user2.id);
cy.apiAddUserToChannel(testChannel.id, user3.id);
// # Post a sample message
return cy.postMessageAs({sender: user1, message, channelId: testChannel.id});
}).then((post) => {
testPost = post.data;
// # Post a reply
return cy.postMessageAs({sender: user1, message: replyMessage, channelId: testChannel.id, rootId: testPost.id});
}).then((post) => {
replyPost = post.data;
// # Create new DM channel
return cy.apiCreateDirectChannel([user1.id, user2.id]);
}).then(({channel}) => {
dmChannel = channel;
// # Create new DM channel
return cy.apiCreateGroupChannel([user1.id, user2.id, user3.id]);
}).then(({channel}) => {
gmChannel = channel;
console.log('this one');
// # Create a private channel to Move Thread to
return cy.apiCreateChannel(testTeam.id, 'private', 'Private');
}).then(({channel}) => {
privateChannel = channel;
console.log('no, this one');
// # Create a second channel to Move Thread to
return cy.apiCreateChannel(testTeam.id, 'movethread', 'Move Thread');
}).then(({channel}) => {
otherChannel = channel;
// # Got to Test channel
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
});
});
it('Move root post from public channel to another public channel', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').click();
// # Move Thread
moveThread({channelId: otherChannel.id});
// * Assert post has been moved
verifyMovedMessage({post: testPost});
});
it('Move reply post from public channel to another public channel', () => {
// # Open the RHS with replies to the root post
cy.uiClickPostDropdownMenu(testPost.id, 'Reply', 'CENTER');
// * Assert RHS is open
cy.get('#rhsContainer').should('be.visible');
// # Click on ... button of reply post
cy.clickPostDotMenu(replyPost.id, 'RHS_COMMENT');
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').click();
// * Move Thread
moveThread({channelId: otherChannel.id});
// * Assert post has been moved
verifyMovedMessage({post: testPost});
});
it('Move public channel post to Private channel', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').click();
// # Move Thread
moveThread({channelId: privateChannel.id});
// * Assert post has been moved
verifyMovedMessage({post: testPost});
});
it('Move public channel post to GM', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').click();
// # Move Thread
moveThread({channelId: gmChannel.id});
// * Assert post has been moved
verifyMovedMessage({post: testPost});
});
it('Move public channel post to DM', () => {
// # Check if ... button is visible in last post right side
cy.get(`#CENTER_button_${testPost.id}`).should('not.be.visible');
// # Click on ... button of last post
cy.clickPostDotMenu(testPost.id);
// * Assert availability of the Move Thread menu-item
cy.findByText('Move Thread').click();
// # Move Thread
moveThread({channelId: dmChannel.id});
// * Assert post has been moved
verifyMovedMessage({post: testPost});
});
/**
* Verify that the post has been moved
*
* @param {Post} post
*/
const verifyMovedMessage = ({post}) => {
// * Assert post has been moved
cy.getLastPostId().then((id) => {
// * Assert last post is visible
cy.get(`#${id}_message`).should('be.visible').within(() => {
// * Assert the text in the preview matches the original post message
cy.get(`#postMessageText_${post.id}`).should('be.visible').should('contain.text', post.message);
});
// # Cleanup
cy.apiDeletePost(id);
});
};
/**
* Move Thread with optional comment.
*
*/
const moveThread = () => {
// * Assert visibility of the Move Thread modal
cy.get('#move-thread-modal').should('be.visible').within(() => {
// * Assert channel select is not existent
cy.get('.move-thread__select').should('not.exist');
// * Assert if button is enabled
cy.get('.GenericModal__button.confirm').should('not.be.disabled');
// * Assert Notification is shown
cy.findByTestId('notification-text').should('be.visible').should('contain.text', 'Moving this thread changes who has access');
});
};
});

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

@@ -714,4 +714,13 @@ const defaultServerConfig: AdminConfig = {
Directory: './export',
RetentionDays: 30,
},
WranglerSettings: {
PermittedWranglerRoles: [],
AllowedEmailDomain: [],
MoveThreadMaxCount: 30,
MoveThreadToAnotherTeamEnable: true,
MoveThreadFromPrivateChannelEnable: true,
MoveThreadFromDirectMessageChannelEnable: true,
MoveThreadFromGroupMessageChannelEnable: true,
},
};