snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 1s
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 1s
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
// 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 @channel
|
||||
|
||||
describe('Channel user count', () => {
|
||||
let testTeam;
|
||||
let secondUser;
|
||||
before(() =>
|
||||
|
||||
// # Create a new user and assign it to a team
|
||||
cy.apiInitSetup().then(({team}) => {
|
||||
testTeam = team;
|
||||
|
||||
// # Visit 'off-topic' channel for this team, as sysadmin
|
||||
cy.visit(`/${testTeam.name}/channels/off-topic`);
|
||||
}),
|
||||
);
|
||||
|
||||
it('MM-T481 User count is updated if user automatically joins channel', () => {
|
||||
const initialUserCount = 2;
|
||||
|
||||
// * Assert channel user count displays '2' (system admin + main user)
|
||||
cy.get('#channelMemberCountText').should('be.visible').and('have.text', `${initialUserCount}`);
|
||||
cy.get('#channelMemberCountText').invoke('text').as('initialUserCountText');
|
||||
|
||||
// # Create another user
|
||||
cy.apiCreateUser().then(({user}) => {
|
||||
secondUser = user;
|
||||
|
||||
// # Add new user (secondUser) to current team
|
||||
cy.apiAddUserToTeam(testTeam.id, secondUser.id);
|
||||
});
|
||||
|
||||
cy.apiGetChannelByName(testTeam.name, 'off-topic').then(({channel}) => {
|
||||
// # Add secondUser to 'off-topic' channel
|
||||
cy.apiAddUserToChannel(channel.id, secondUser.id);
|
||||
});
|
||||
|
||||
// * Assert channel user count now displays '3' (system admin + main user + second user)
|
||||
cy.get('#channelMemberCountText').should('be.visible').and('have.text', `${initialUserCount + 1}`);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import * as TIMEOUTS from '@/fixtures/timeouts';
|
||||
import * as MESSAGES from '@/fixtures/messages';
|
||||
|
||||
// ***************************************************************
|
||||
// [#] 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.
|
||||
// ***************************************************************
|
||||
|
||||
// Group: @channels @multi_team_and_dm
|
||||
|
||||
describe('Multi-Team + DMs', () => {
|
||||
let userA;
|
||||
let userB;
|
||||
let testChannelUrl;
|
||||
|
||||
const away = {name: 'away', ariaLabel: 'Away', message: 'You are now away', className: 'icon-clock'};
|
||||
const online = {name: 'online', ariaLabel: 'Online', message: 'You are now online', className: 'icon-check', profileClassName: 'icon-check-circle'};
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
userA = user;
|
||||
testChannelUrl = `/${team.name}/channels/town-square`;
|
||||
|
||||
cy.apiCreateUser().then(({user: otherUser}) => {
|
||||
userB = otherUser;
|
||||
cy.apiAddUserToTeam(team.id, userB.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T423 Online Status - Statuses update in center, in member icon drop-down, and in DM LHS sidebar', () => {
|
||||
// # Login with UserB and post a message to UserA
|
||||
cy.apiLogin(userB);
|
||||
cy.visit(testChannelUrl);
|
||||
cy.postMessage(MESSAGES.SMALL);
|
||||
cy.uiAddDirectMessage().click();
|
||||
cy.get('#selectItems').typeWithForce(userA.username);
|
||||
cy.findByText('Loading').should('be.visible');
|
||||
cy.findByText('Loading').should('not.exist');
|
||||
cy.get('#multiSelectList').findByText(`@${userA.username}`).click();
|
||||
cy.findByText('Go').click();
|
||||
cy.postMessage(MESSAGES.SMALL);
|
||||
|
||||
// # Set online status and verify it's changed as the initial status
|
||||
setStatus(online.name, online.profileClassName);
|
||||
verifyUserStatus(away);
|
||||
|
||||
// # Login with UserA and verify Status of UserB
|
||||
cy.apiLogout();
|
||||
cy.apiLogin(userA);
|
||||
cy.visit(testChannelUrl);
|
||||
|
||||
// * Verify status shown at username in the DM list on LHS
|
||||
cy.get(`[aria-label^="${userB.username}"]`).
|
||||
children().
|
||||
find('i').should('have.class', 'status-away');
|
||||
|
||||
// * Verify user's status show in the members list on RHS
|
||||
cy.get('#member_rhs').click();
|
||||
cy.get('#rhsContainer').should('be.visible');
|
||||
cy.get(`[data-testid="memberline-${userB.id}"]`).
|
||||
should('be.visible').
|
||||
children('div.Avatar-IGMzc').
|
||||
children().
|
||||
find('svg').should('have.attr', 'aria-label', 'Away');
|
||||
});
|
||||
});
|
||||
|
||||
function setStatus(status, icon) {
|
||||
cy.apiUpdateUserStatus(status);
|
||||
cy.uiGetProfileHeader().
|
||||
find('i').
|
||||
and('have.class', icon);
|
||||
}
|
||||
|
||||
function verifyUserStatus(testCase) {
|
||||
// # Clear then type '/'
|
||||
cy.uiGetPostTextBox().clear().type('/');
|
||||
|
||||
// * Verify that the suggestion list is visible
|
||||
cy.get('#suggestionList').should('be.visible');
|
||||
|
||||
// # Post slash command to change user status
|
||||
cy.uiGetPostTextBox().type(`${testCase.name}{enter}`).wait(TIMEOUTS.ONE_HUNDRED_MILLIS).type('{enter}');
|
||||
|
||||
// * Get last post and verify system message
|
||||
cy.getLastPost().within(() => {
|
||||
cy.findByText(testCase.message);
|
||||
cy.findByText('(Only visible to you)');
|
||||
});
|
||||
|
||||
// * Verify status shown at user profile in LHS
|
||||
cy.uiGetProfileHeader().
|
||||
find('i').
|
||||
and('have.class', testCase.profileClassName || testCase.className);
|
||||
|
||||
// # Post a message
|
||||
cy.postMessage(testCase.name);
|
||||
|
||||
// * Verify that the profile in the posted message shows correct status
|
||||
cy.get('.post__img').last().findByLabelText(testCase.ariaLabel);
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// Stage: @prod
|
||||
// Group: @channels @multi_team_and_dm
|
||||
|
||||
import * as TIMEOUTS from '@/fixtures/timeouts';
|
||||
|
||||
describe('Direct messages: redirections', () => {
|
||||
let testUser;
|
||||
let secondDMUser;
|
||||
let firstDMUser;
|
||||
let testTeam;
|
||||
let offTopicChannelUrl;
|
||||
|
||||
before(() => {
|
||||
// # Create a new team
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testUser = user;
|
||||
testTeam = team;
|
||||
|
||||
offTopicChannelUrl = `/${testTeam.name}/channels/off-topic`;
|
||||
|
||||
cy.apiCreateUser().then(({user: createdUser}) => {
|
||||
firstDMUser = createdUser;
|
||||
cy.apiAddUserToTeam(testTeam.id, firstDMUser.id);
|
||||
});
|
||||
|
||||
// # Create a second test user
|
||||
cy.apiCreateUser().then(({user: createdUser}) => {
|
||||
secondDMUser = createdUser;
|
||||
cy.apiAddUserToTeam(testTeam.id, secondDMUser.id);
|
||||
});
|
||||
|
||||
// # Login as test user
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # View 'off-topic' channel
|
||||
cy.visit(offTopicChannelUrl);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T453_1 Closing a direct message should redirect to town square channel', () => {
|
||||
// # From the 'Direct Messages' menu, find a specific user and send 'hi'
|
||||
sendDirectMessageToUser(firstDMUser, 'hi');
|
||||
|
||||
// # Close the direct message via 'x' button right of the username in the direct messages' list
|
||||
closeDirectMessage(testUser, firstDMUser, testTeam);
|
||||
|
||||
// * Expect to be redirected to town square channel, check channel title and url
|
||||
expectActiveChannelToBe('Town Square', `/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # From the 'Direct Messages' menu, find the same user as before and send 'hi'
|
||||
sendDirectMessageToUser(firstDMUser, 'hi again');
|
||||
|
||||
// # Open channel menu and click Close Direct Message
|
||||
cy.uiOpenChannelMenu('Close Direct Message');
|
||||
|
||||
// * Expect to be redirected to town square channel, check channel title and url
|
||||
expectActiveChannelToBe('Town Square', `/${testTeam.name}/channels/town-square`);
|
||||
});
|
||||
|
||||
it('MM-T453_2 Closing a different direct message should not affect active direct message', () => {
|
||||
// # Send a direct message to a first user
|
||||
sendDirectMessageToUser(firstDMUser, 'hi first');
|
||||
|
||||
// # Send a message to a second user
|
||||
sendDirectMessageToUser(secondDMUser, 'hi second');
|
||||
|
||||
// # Close the direct message previously opened with the first user
|
||||
closeDirectMessage(testUser, firstDMUser, testTeam);
|
||||
|
||||
// * Expect channel title and url to secondDMUser's username
|
||||
expectActiveChannelToBe(secondDMUser.username, `/messages/@${secondDMUser.username}`);
|
||||
});
|
||||
|
||||
it('MM-T453_3 Changing URL to root url when viewing a direct message should redirect to direct message', () => {
|
||||
// # Send a direct message to a first user
|
||||
sendDirectMessageToUser(firstDMUser, 'hi');
|
||||
|
||||
// # Visit root url
|
||||
cy.visit('/');
|
||||
|
||||
// * Expect channel title and url to firstDMUser's username
|
||||
expectActiveChannelToBe(firstDMUser.username, `/messages/@${firstDMUser.username}`);
|
||||
});
|
||||
});
|
||||
|
||||
const expectActiveChannelToBe = (title, url) => {
|
||||
// * Expect channel title to match title passed in argument
|
||||
cy.get('#channelHeaderTitle').
|
||||
should('be.visible').
|
||||
and('contain.text', title);
|
||||
|
||||
// * Expect url to match url passed in argument
|
||||
cy.url().should('contain', url);
|
||||
};
|
||||
|
||||
const sendDirectMessageToUser = (user, message) => {
|
||||
// # Open a new direct message with firstDMUser
|
||||
cy.uiAddDirectMessage().click();
|
||||
|
||||
// # Type username
|
||||
cy.get('#selectItems input').should('be.enabled').typeWithForce(`@${user.username}`).wait(TIMEOUTS.ONE_SEC);
|
||||
|
||||
// * Expect user count in the list to be 1
|
||||
cy.get('#multiSelectList').
|
||||
should('be.visible').
|
||||
children().
|
||||
should('have.length', 1);
|
||||
|
||||
// # Select first user in the list
|
||||
cy.get('body').
|
||||
type('{downArrow}').
|
||||
type('{enter}');
|
||||
|
||||
// # Click on "Go" in the group message's dialog to begin the conversation
|
||||
cy.get('#saveItems').click();
|
||||
|
||||
// * Expect the channel title to be the user's username
|
||||
// In the channel header, it seems there is a space after the username, justifying the use of contains.text instead of have.text
|
||||
cy.get('#channelHeaderTitle').should('be.visible').and('contain.text', user.username);
|
||||
|
||||
// # Type message and send it to the user
|
||||
cy.uiGetPostTextBox().
|
||||
type(message).
|
||||
type('{enter}');
|
||||
};
|
||||
|
||||
const closeDirectMessage = (sender, recipient, team) => {
|
||||
// # Find the username in the 'Direct Messages' list and trigger the 'x' button to appear (hover over the username)
|
||||
cy.apiGetChannelsForUser(sender.id, team.id).then(({channels}) => {
|
||||
// Get the name of the channel to build the CSS selector for that specific DM link in the sidebar
|
||||
const channelDmWithFirstUser = channels.find((channel) =>
|
||||
channel.type === 'D' && channel.name.includes(recipient.id),
|
||||
);
|
||||
|
||||
// # Close the DM via sidebar channel menu
|
||||
cy.uiGetChannelSidebarMenu(channelDmWithFirstUser.name, true).within(() => {
|
||||
cy.findByText('Close Conversation').click();
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
// 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 @multi_team_and_dm
|
||||
|
||||
describe('Multi-user group messages', () => {
|
||||
let testUser;
|
||||
let testTeam;
|
||||
before(() => {
|
||||
// # Create a new team
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testUser = user;
|
||||
testTeam = team;
|
||||
|
||||
// # Add 3 users to the team
|
||||
Cypress._.times(3, () => createUserAndAddToTeam(testTeam));
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T1799 Should Close Group Message from channel menu', () => {
|
||||
// # Login as test user
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Go to town-square channel
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open the 'Direct messages' dialog to create a new direct message
|
||||
cy.uiAddDirectMessage().should('be.visible').click();
|
||||
|
||||
// # Add 3 users to a group message
|
||||
addUsersToGMViaModal(3);
|
||||
|
||||
// * Check that the list is populated
|
||||
cy.get('.react-select__multi-value').should('have.length', 3);
|
||||
|
||||
// # Click on "Go" in the group message's dialog to begin the conversation
|
||||
cy.get('#saveItems').click();
|
||||
|
||||
// # Click channel dropdown icon to open menu
|
||||
cy.get('#channelHeaderTitle').click();
|
||||
|
||||
// # Click 'close' item
|
||||
cy.findByText('Close Group Message').should('be.visible').click();
|
||||
|
||||
// * Validate that GM is closed and we are redirected
|
||||
expectActiveChannelToBe('Town Square', '/town-square');
|
||||
});
|
||||
});
|
||||
|
||||
// Helper functions
|
||||
|
||||
const expectActiveChannelToBe = (title, url) => {
|
||||
// * Expect channel title to match title passed in argument
|
||||
cy.get('#channelHeaderTitle').
|
||||
should('be.visible').
|
||||
and('contain.text', title);
|
||||
|
||||
// * Expect url to match url passed in argument
|
||||
cy.url().should('contain', url);
|
||||
};
|
||||
|
||||
const createUserAndAddToTeam = (team) => {
|
||||
cy.apiCreateUser({prefix: 'gm'}).then(({user}) =>
|
||||
cy.apiAddUserToTeam(team.id, user.id),
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a given amount of numbers to a direct message group
|
||||
* @param {number} userCountToAdd
|
||||
*/
|
||||
const addUsersToGMViaModal = (userCountToAdd) => {
|
||||
// # Ensure there are enough selectable users in the list
|
||||
cy.get('#multiSelectList').
|
||||
should('be.visible').
|
||||
children().
|
||||
should('have.length.gte', userCountToAdd);
|
||||
|
||||
// # Add the first user from the top of the list, as many times as requested by 'userCountToAdd'
|
||||
Cypress._.times(userCountToAdd, () => {
|
||||
cy.get('#multiSelectList').
|
||||
children().
|
||||
first().
|
||||
click();
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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 @multi_team_and_dm
|
||||
|
||||
describe('Multi Team and DM', () => {
|
||||
let testChannel;
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let searchTerm;
|
||||
const prefix = 'testuser';
|
||||
|
||||
before(() => {
|
||||
// # Setup with the new team, channel and user
|
||||
cy.apiInitSetup().then(({team, channel, user}) => {
|
||||
testTeam = team;
|
||||
testChannel = channel;
|
||||
testUser = user;
|
||||
searchTerm = user.username;
|
||||
|
||||
// # Create 52 users so the user must page forward in the dm list
|
||||
Cypress._.times(52, () => {
|
||||
cy.apiCreateUser({prefix}).then(() => {
|
||||
cy.apiAddUserToTeam(testTeam.id, user.id);
|
||||
});
|
||||
});
|
||||
|
||||
// # Login with testUser and visit test channel
|
||||
cy.apiLogin(testUser);
|
||||
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T446 DM More... searching from page 2 of user list', () => {
|
||||
// # Open the Direct Message modal
|
||||
cy.uiAddDirectMessage().click();
|
||||
|
||||
// # Move to the next page of users
|
||||
cy.findByText('Next').click();
|
||||
cy.findByText('Previous').should('exist');
|
||||
|
||||
// # Enter a search term
|
||||
cy.findByRole('combobox', {name: 'Search for people'}).typeWithForce(searchTerm);
|
||||
|
||||
// * Assert that the previous / next links do not appear since there should only be 1 record displayed
|
||||
cy.findByText('Next').should('not.exist');
|
||||
cy.findByText('Previous').should('not.exist');
|
||||
|
||||
// * Assert that the search term does not return wrong user(s)
|
||||
cy.findAllByText(prefix).should('not.exist');
|
||||
|
||||
// * Assert that the search term returns the correct user and is visible
|
||||
cy.findByText(`${searchTerm}@sample.mattermost.com`).should('be.visible');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 @multi_team_and_dm
|
||||
|
||||
import {getRandomId} from '@/utils';
|
||||
|
||||
describe('Multi Team and DM', () => {
|
||||
let testChannel;
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
const unique = `${getRandomId(4)}`;
|
||||
|
||||
before(() => {
|
||||
// # Setup with the new team, channel and user
|
||||
cy.apiInitSetup().then(({team, channel, user}) => {
|
||||
testTeam = team;
|
||||
testChannel = channel;
|
||||
testUser = user;
|
||||
|
||||
// # Create 4 test users with prefix 'common'
|
||||
Cypress._.times(4, () => {
|
||||
cy.apiCreateUser({prefix: 'common'}).then(() => {
|
||||
cy.apiAddUserToTeam(testTeam.id, user.id);
|
||||
});
|
||||
});
|
||||
|
||||
// # Create 2 test users with random prefix
|
||||
Cypress._.times(2, () => {
|
||||
cy.apiCreateUser({prefix: unique}).then(() => {
|
||||
cy.apiAddUserToTeam(testTeam.id, user.id);
|
||||
});
|
||||
});
|
||||
|
||||
// # Login with testUser and visit test channel
|
||||
cy.apiLogin(testUser);
|
||||
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T444 DM More... show user count', () => {
|
||||
// # Open the Direct Message modal
|
||||
cy.uiAddDirectMessage().click();
|
||||
|
||||
cy.get('#multiSelectHelpMemberInfo > :nth-child(2)').then((number) => {
|
||||
// # Grab total number of users before filter applied
|
||||
const totalUsers = number.text().split(' ').slice(2, 3);
|
||||
|
||||
// * Assert that 2 unique users are displayed
|
||||
cy.findByRole('combobox', {name: 'Search for people'}).typeWithForce(unique).then(() => {
|
||||
cy.get('#multiSelectList').within(() => {
|
||||
cy.get('.more-modal__details').should('have.length', 2);
|
||||
});
|
||||
|
||||
// * Assert that total number of users is displayed correctly
|
||||
cy.get('#multiSelectHelpMemberInfo').should('contain', 'Use ↑↓ to browse, ↵ to select. You can add 7 more people. ').should('contain', `2 of ${totalUsers} members`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,138 @@
|
||||
// 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 @multi_team_and_dm
|
||||
|
||||
import * as TIMEOUTS from '@/fixtures/timeouts';
|
||||
|
||||
describe('Channel', () => {
|
||||
let testTeamId;
|
||||
|
||||
before(() => {
|
||||
// # Login as test user and visit town-square
|
||||
cy.apiInitSetup({loginAfter: true}).then(({team}) => {
|
||||
testTeamId = team.id;
|
||||
cy.visit(`/${team.name}/channels/town-square`);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T422_1 Channel name already taken for public channel', () => {
|
||||
// # Create a new public channel
|
||||
createNewChannel('unique-public', false, testTeamId).as('channel');
|
||||
cy.reload();
|
||||
|
||||
cy.get('@channel').then((channel) => {
|
||||
// * Verify new public channel cannot be created with existing public channel name
|
||||
verifyChannel(channel);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T422_2 Channel name already taken for private channel', () => {
|
||||
// # Create a new private channel
|
||||
createNewChannel('unique-private', true, testTeamId).as('channel');
|
||||
cy.reload();
|
||||
|
||||
cy.get('@channel').then((channel) => {
|
||||
// * Verify new private channel cannot be created with existing private channel name
|
||||
verifyChannel(channel);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-43881 Channel name already taken for public channel and changed allows to create', () => {
|
||||
// # Create a new public channel
|
||||
createNewChannel('other-public', false, testTeamId).as('channel');
|
||||
cy.reload();
|
||||
|
||||
cy.get('@channel').then((channel) => {
|
||||
// * Verify new public channel cannot be created with existing public channel name
|
||||
verifyExistingChannelError(channel.name);
|
||||
|
||||
// Update channel name in the input field for new channel
|
||||
cy.get('#input_new-channel-modal-name').should('be.visible').click().type(`${channel.name}1`);
|
||||
cy.wait(TIMEOUTS.HALF_SEC);
|
||||
|
||||
// * Error message saying "A channel with that name already exists" should be removed
|
||||
cy.get('.url-input-error').should('not.exist');
|
||||
|
||||
// * 'Create Channel' button should be enabled
|
||||
cy.findByText('Create channel').should('not.have.class', 'disabled');
|
||||
|
||||
// # Click on Cancel button to move out of New Channel Modal
|
||||
cy.findByText('Cancel').click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a channel with existing name and verify that error is shown
|
||||
* @param {String} newChannelName - New channel name to assign
|
||||
* @param {boolean} makePrivate - Set to false to make public channel (default), otherwise true as private channel
|
||||
*/
|
||||
function verifyExistingChannelError(newChannelName, makePrivate = false) {
|
||||
// Click on '+' button for Public or Private Channel
|
||||
cy.uiBrowseOrCreateChannel('Create new channel');
|
||||
|
||||
if (makePrivate) {
|
||||
cy.get('#public-private-selector-button-P').click();
|
||||
} else {
|
||||
cy.get('#public-private-selector-button-O').click();
|
||||
}
|
||||
|
||||
// Type `newChannelName` in the input field for new channel
|
||||
cy.get('#input_new-channel-modal-name').should('be.visible').click().type(`${newChannelName}{enter}`);
|
||||
|
||||
// * User gets a message saying "A channel with that name already exists"
|
||||
cy.get('.url-input-error').contains('A channel with that URL already exists');
|
||||
|
||||
// * 'Create Channel' button should be disabled
|
||||
cy.findByText('Create channel').should('have.class', 'disabled');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to create public and private channels with existing `channelName` and verifies error
|
||||
* @param {String} channelName - Existing channel name that is also being tested for error
|
||||
*/
|
||||
function verifyChannel(channel) {
|
||||
// # Find current number of channels
|
||||
cy.uiGetLhsSection('CHANNELS').find('.SidebarChannel').its('length').as('origChannelLength');
|
||||
|
||||
// * Verify channel `channelName` exists
|
||||
cy.uiGetLhsSection('CHANNELS').should('contain', channel.display_name);
|
||||
|
||||
// * Verify new public channel cannot be created with existing public channel name
|
||||
verifyExistingChannelError(channel.name);
|
||||
|
||||
// # Click on Cancel button to move out of New Channel Modal
|
||||
cy.findByText('Cancel').click();
|
||||
|
||||
// * Verify new private channel cannot be created with existing public channel name
|
||||
verifyExistingChannelError(channel.name, true);
|
||||
|
||||
// # Click on Cancel button to move out of New Channel Modal
|
||||
cy.findByText('Cancel').click();
|
||||
|
||||
// * Verify the number of channels is still the same as before
|
||||
cy.get('@origChannelLength').then((origChannelLength) => {
|
||||
cy.uiGetLhsSection('CHANNELS').find('.SidebarChannel').its('length').should('equal', origChannelLength);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new channel via API
|
||||
* @param {String} name Name of the channel. This will be used for both name and display_name
|
||||
* @param {Boolean} isPrivate Should the channel be private
|
||||
* @param {String} testTeamId Team where to create a channel
|
||||
* @returns body of request
|
||||
*/
|
||||
function createNewChannel(name, isPrivate = false, testTeamId) {
|
||||
const makePrivate = isPrivate ? 'P' : 'O';
|
||||
|
||||
return cy.apiCreateChannel(testTeamId, name, name, makePrivate, 'Let us chat here').its('channel');
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// 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 @multi_team_and_dm
|
||||
|
||||
describe('Close group messages', () => {
|
||||
let testUser;
|
||||
let otherUser1;
|
||||
let otherUser2;
|
||||
let testTeam;
|
||||
|
||||
before(() => {
|
||||
cy.apiAdminLogin();
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testUser = user;
|
||||
testTeam = team;
|
||||
|
||||
cy.apiCreateUser({prefix: 'aaa'}).then(({user: newUser}) => {
|
||||
otherUser1 = newUser;
|
||||
cy.apiAddUserToTeam(team.id, newUser.id);
|
||||
});
|
||||
cy.apiCreateUser({prefix: 'bbb'}).then(({user: newUser}) => {
|
||||
otherUser2 = newUser;
|
||||
cy.apiAddUserToTeam(team.id, newUser.id);
|
||||
});
|
||||
|
||||
// # Login as test user and go to town square
|
||||
cy.apiLogin(testUser);
|
||||
cy.visit(`/${team.name}/channels/town-square`);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T474 - GM: Favorite, and close', () => {
|
||||
createAndVisitGMChannel([otherUser1, otherUser2]).then((channel) => {
|
||||
// # Favorite the channel
|
||||
cy.get('#toggleFavorite').click();
|
||||
|
||||
// * Check that the channel is on top of favorites list
|
||||
cy.uiGetLhsSection('FAVORITES').find('.SidebarChannel').first().should('contain', channel.display_name.replace(`, ${testUser.username}`, ''));
|
||||
|
||||
// # Click on the x button on the sidebar channel item
|
||||
cy.uiGetChannelSidebarMenu(channel.name, true).within(() => {
|
||||
cy.findByText('Close Conversation').click();
|
||||
});
|
||||
|
||||
verifyChannelWasProperlyClosed(channel.name);
|
||||
});
|
||||
});
|
||||
|
||||
function createAndVisitGMChannel(users = []) {
|
||||
const userIds = users.map((user) => user.id);
|
||||
return cy.apiCreateGroupChannel(userIds).then(({channel}) => {
|
||||
// # Visit the new channel
|
||||
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
|
||||
|
||||
// * Verify channel's display name
|
||||
const displayName = users.
|
||||
map((member) => member.username).
|
||||
sort((a, b) => a.localeCompare(b, 'en', {numeric: true})).
|
||||
join(', ');
|
||||
cy.get('#channelHeaderTitle').should('contain', displayName);
|
||||
|
||||
return cy.wrap(channel);
|
||||
});
|
||||
}
|
||||
|
||||
// Make sure that the current channel is Town Square and that the
|
||||
// channel identified by the passed name is no longer in the channel
|
||||
// sidebar
|
||||
function verifyChannelWasProperlyClosed(channelName) {
|
||||
// * Make sure that we have switched channels
|
||||
cy.get('#channelHeaderTitle').should('contain', 'Town Square');
|
||||
|
||||
// * Make sure the old DM no longer exists
|
||||
cy.get('#sidebarItem_' + channelName).should('not.exist');
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,197 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// Stage: @prod
|
||||
// Group: @channels @multi_team_and_dm
|
||||
|
||||
import * as TIMEOUTS from '@/fixtures/timeouts';
|
||||
|
||||
describe('Multi-user group messages', () => {
|
||||
let testUser;
|
||||
let testTeam;
|
||||
const userIds = [];
|
||||
const userList = [];
|
||||
let groupChannel;
|
||||
|
||||
before(() => {
|
||||
// # Create a new team
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testUser = user;
|
||||
testTeam = team;
|
||||
|
||||
// # Add 3 users to the team that should be alphabetically sorted
|
||||
['0aadam', '0aabadam', 'beatrice'].forEach((prefix) => {
|
||||
createTestUser(prefix, team);
|
||||
});
|
||||
|
||||
// # Create a GM with at least 3 users
|
||||
['charlie', 'diana', 'eddie'].forEach((name) => {
|
||||
cy.apiCreateUser({prefix: name, bypassTutorial: true}).then(({user: groupUser}) => {
|
||||
cy.apiAddUserToTeam(testTeam.id, groupUser.id);
|
||||
userIds.push(groupUser.id);
|
||||
userList.push(groupUser);
|
||||
});
|
||||
});
|
||||
|
||||
// # Add test user to the list of group members
|
||||
userIds.push(testUser.id);
|
||||
|
||||
cy.apiCreateGroupChannel(userIds).then(({channel}) => {
|
||||
groupChannel = channel;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T459 Group Messaging: Add first user', () => {
|
||||
const searchTerm = '0aa';
|
||||
|
||||
// # Login as test user
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Go to town-square channel
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
cy.contains('#channelHeaderTitle', 'Town Square');
|
||||
|
||||
// # Open the 'Direct messages' dialog
|
||||
cy.uiAddDirectMessage().click().wait(TIMEOUTS.ONE_SEC);
|
||||
cy.findByRole('dialog', {name: 'Direct Messages'}).should('be.visible').wait(TIMEOUTS.ONE_SEC);
|
||||
|
||||
// # Start typing part of a username that matches previously created users
|
||||
cy.findByRole('combobox', {name: 'Search for people'}).
|
||||
typeWithForce(searchTerm).
|
||||
wait(TIMEOUTS.ONE_SEC);
|
||||
|
||||
// * Expect user list to only contain usernames matching the query term and to be sorted alphabetically
|
||||
expectUserListSortedAlphabetically(searchTerm);
|
||||
|
||||
// # With the arrow and enter keys, select the first user that matches our search query
|
||||
cy.get('body').
|
||||
type('{downarrow}').
|
||||
type('{enter}');
|
||||
|
||||
// * Expect to have the selected user's username to be displayed inside the search input
|
||||
cy.get('.react-select__multi-value').
|
||||
should('be.visible').
|
||||
and('have.length', 1).
|
||||
then(($selectedUser) => {
|
||||
// # Get the selected user's username
|
||||
const selectedUserName = $selectedUser.text();
|
||||
|
||||
// * Expect user list to not contain selected user, not be filtered, but still in alphabetical order
|
||||
expectUserListSortedAlphabetically(selectedUserName, true);
|
||||
});
|
||||
|
||||
// * Expect to have a remove button ('x') present next to the selected username (previous step)
|
||||
cy.get('.react-select__multi-value__remove').
|
||||
should('be.visible').
|
||||
and('have.length', 1);
|
||||
|
||||
// * Expect search bar to have focus
|
||||
cy.get('.react-select__multi-value').next().find('input').should('have.focus');
|
||||
|
||||
// * Expect previous search term to be cleared from search bar
|
||||
cy.get('#selectItems input').should('have.text', '');
|
||||
|
||||
// * Expect the help section showing that we 6 more people can be added to the message
|
||||
cy.get('#multiSelectHelpMemberInfo').
|
||||
should('be.visible').
|
||||
and('contain.text', 'You can add 6 more people');
|
||||
});
|
||||
|
||||
it('MM-T468 Group Messaging: Add member to existing GM', () => {
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Add some messages to the channel
|
||||
cy.visit(`/${testTeam.name}/channels/${groupChannel.name}`);
|
||||
cy.postMessage('some');
|
||||
cy.postMessage('historical');
|
||||
cy.postMessage('messages');
|
||||
|
||||
// # Open channel menu and click Add Members
|
||||
cy.uiOpenChannelMenu('Members');
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// * Verify message says: "This will start a new conversation. If you're adding a lot of people, consider creating a private channel instead."
|
||||
cy.get('#moreDmModal').should('be.visible');
|
||||
const warnMessage = 'This will start a new conversation. If you\'re adding a lot of people, consider creating a private channel instead.';
|
||||
cy.contains(warnMessage).should('be.visible');
|
||||
|
||||
// * Verify users are listed in the GM box
|
||||
userList.forEach((user) => {
|
||||
cy.get('.react-select__multi-value div').should('contain', user.username);
|
||||
});
|
||||
|
||||
// # Type a search term and select an autocomplete option.
|
||||
cy.get('#selectItems input').typeWithForce('beatrice');
|
||||
cy.get('.loading-screen').should('not.exist');
|
||||
cy.contains('#multiSelectList .clickable', 'beatrice').should('be.visible'); // .click(); runs into detached dom element
|
||||
cy.get('#selectItems input').typeWithForce('{enter}');
|
||||
|
||||
// # Click Go
|
||||
cy.get('button#saveItems').click({force: true});
|
||||
|
||||
// * Modal closes
|
||||
cy.get('#moreDmModal').should('not.exist');
|
||||
cy.wait(TIMEOUTS.ONE_SEC);
|
||||
|
||||
// * Original messages does not exist
|
||||
cy.contains('.post-message__text', 'historical').should('not.exist');
|
||||
|
||||
cy.contains('p.channel-intro__text', 'This is the start of your group message history with');
|
||||
|
||||
// * New user is added to the GM
|
||||
cy.uiGetRHS().contains(testUser.username).should('be.visible');
|
||||
|
||||
// * Other users are still there
|
||||
userList.forEach((user) => {
|
||||
cy.uiGetRHS().contains(user.username).scrollIntoView().should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Helper functions
|
||||
|
||||
/**
|
||||
* Check that the user list inside the direct messages dialog is sorted alphabetically
|
||||
* - Numbers are included in the sorting logic
|
||||
* - Lowercase letters come before uppercase letters
|
||||
* @param {string?} filterString Optional, ensure all results in the list match a certain string, an autocomplete filter
|
||||
*/
|
||||
const expectUserListSortedAlphabetically = (filterString, excludeFilter = false) => {
|
||||
return cy.get('#multiSelectList').
|
||||
should('be.visible').
|
||||
children().
|
||||
each(($child) => {
|
||||
// To limit the amount of text fetched, only get the text content from the displayed name and username (without email)
|
||||
const currentChildText = $child.find('[id*="displayedUserName"]').text();
|
||||
const immediateNextSibling = $child.next();
|
||||
|
||||
// * Expect all usernames displayed in the in user list to be sorted alphabetically
|
||||
if (immediateNextSibling.length) {
|
||||
const siblingText = immediateNextSibling.find('[id*="displayedUserName"]').text();
|
||||
const stringComparison = currentChildText.localeCompare(siblingText, 'en');
|
||||
|
||||
// Both strings equal -> 0, currentChildText comes before siblingText -> -1 (could vary by browser but should not be negative)
|
||||
expect(stringComparison, `${currentChildText} should be before ${siblingText}`).to.be.lte(0);
|
||||
}
|
||||
|
||||
if (excludeFilter) {
|
||||
// * If a user is selected, ensure remaining users list does not contain the selected user
|
||||
expect(currentChildText).to.not.contain(filterString);
|
||||
} else {
|
||||
// * Optionally, ensure all usernames match the autocomplete input
|
||||
expect(currentChildText).to.contain(filterString);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a user and assign it to a team
|
||||
* @param {string} prefix Prefix to add to the username
|
||||
* @param {string} team Team object, reference to the team we want to add the user to
|
||||
*/
|
||||
const createTestUser = (prefix, team) => {
|
||||
cy.apiCreateUser({prefix}).then(({user}) =>
|
||||
cy.apiAddUserToTeam(team.id, user.id),
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,164 @@
|
||||
// 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 @multi_team_and_dm
|
||||
|
||||
import {beRead, beUnread} from '@/support/assertions';
|
||||
import * as TIMEOUTS from '@/fixtures/timeouts';
|
||||
|
||||
describe('Multi-user group header', () => {
|
||||
let testUser;
|
||||
let testTeam;
|
||||
const userIds = [];
|
||||
const userList = [];
|
||||
let groupChannel;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testUser = user;
|
||||
testTeam = team;
|
||||
|
||||
// # create a GM with at least 3 users
|
||||
['charlie', 'diana', 'eddie'].forEach((name) => {
|
||||
cy.apiCreateUser({prefix: name, bypassTutorial: true}).then(({user: groupUser}) => {
|
||||
cy.apiAddUserToTeam(testTeam.id, groupUser.id);
|
||||
userIds.push(groupUser.id);
|
||||
userList.push(groupUser);
|
||||
});
|
||||
});
|
||||
|
||||
// # add test user to the list of group members
|
||||
userIds.push(testUser.id);
|
||||
|
||||
cy.apiCreateGroupChannel(userIds).then(({channel}) => {
|
||||
groupChannel = channel;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T472 Add a channel header to a GM', () => {
|
||||
cy.apiLogin(testUser);
|
||||
cy.visit(`/${testTeam.name}/channels/${groupChannel.name}`);
|
||||
|
||||
const header = 'peace and progress';
|
||||
|
||||
// * Verify that no channel header is set
|
||||
cy.get('#channel-header').within(() => {
|
||||
cy.findByText('Add a channel header').should('not.be.visible');
|
||||
});
|
||||
|
||||
// # Force click on button which is hidden and shows on hover
|
||||
cy.findByText('Add a channel header').click({force: true});
|
||||
|
||||
// * Verify the modal open to add header
|
||||
cy.get('#editChannelHeaderModalLabel').should('be.visible').wait(TIMEOUTS.ONE_SEC);
|
||||
|
||||
// # Add the header in the modal
|
||||
cy.findByPlaceholderText('Enter the Channel Header').should('be.visible').type(`${header}{enter}`);
|
||||
|
||||
// # Wait for modal to disappear
|
||||
cy.waitUntil(() => cy.get('#editChannelHeaderModalLabel').should('not.be.visible'));
|
||||
|
||||
// * text appears in the top center panel
|
||||
cy.get('#channel-header').within(() => {
|
||||
cy.findByText(header).should('be.visible');
|
||||
});
|
||||
|
||||
checkSystemMessage('updated the channel header');
|
||||
|
||||
// * Channel is marked as read for the current user
|
||||
cy.get(`#sidebarItem_${groupChannel.name}`).should(beRead);
|
||||
|
||||
// * Channel is marked as unread for other user
|
||||
cy.apiLogout();
|
||||
cy.apiLogin(userList[0]);
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
cy.get(`#sidebarItem_${groupChannel.name}`).should(beUnread);
|
||||
cy.apiLogout();
|
||||
});
|
||||
|
||||
it('MM-T473_1 Edit GM channel header', () => {
|
||||
// # open existing GM
|
||||
cy.apiLogin(testUser);
|
||||
cy.visit(`/${testTeam.name}/channels/${groupChannel.name}`);
|
||||
|
||||
// * Verify that channel header is set
|
||||
cy.get('#channel-header').within(() => {
|
||||
cy.findByText('Add a channel header').should('not.exist');
|
||||
});
|
||||
|
||||
const header = 'In pursuit of peace and progress';
|
||||
editHeader(header);
|
||||
|
||||
// * Header text appears at the top
|
||||
cy.get('#channel-header').within(() => {
|
||||
cy.findByText(header).should('be.visible');
|
||||
});
|
||||
|
||||
checkSystemMessage('updated the channel header');
|
||||
|
||||
// * Channel is marked as unread for other users
|
||||
cy.apiLogout();
|
||||
cy.apiLogin(userList[0]);
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
cy.get(`#sidebarItem_${groupChannel.name}`).should(beUnread);
|
||||
cy.apiLogout();
|
||||
});
|
||||
|
||||
it('MM-T473_2 Edit GM channel header', () => {
|
||||
// # Open existing GM
|
||||
cy.apiLogin(testUser);
|
||||
cy.visit(`/${testTeam.name}/channels/${groupChannel.name}`);
|
||||
|
||||
// * Verify that channel header is set
|
||||
cy.get('#channel-header').within(() => {
|
||||
cy.findByText('Add a channel header').should('not.exist');
|
||||
});
|
||||
|
||||
const header = `In pursuit of peace and progress by @${testUser.username}`;
|
||||
editHeader(header);
|
||||
|
||||
// * Header text appears at the top
|
||||
cy.get('#channel-header').within(() => {
|
||||
// * Verify mention is present
|
||||
cy.get('.mention-link').should('be.visible').and('have.text', `@${testUser.username}`);
|
||||
|
||||
// * Verify its not highlighted
|
||||
cy.get('.mention--highlight').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
function editHeader(header) {
|
||||
// # Click edit header
|
||||
cy.uiOpenChannelMenu('');
|
||||
cy.findByRole('menuitem', {name: 'Settings'}).trigger('mouseover');
|
||||
cy.findByText('Edit Header').click();
|
||||
|
||||
// * Verify the modal open to add header
|
||||
cy.get('#editChannelHeaderModalLabel').should('be.visible').wait(TIMEOUTS.ONE_SEC);
|
||||
|
||||
// # Add the header in the modal
|
||||
cy.get('textarea#edit_textbox').should('be.visible').clear().type(`${header}{enter}`);
|
||||
|
||||
// # Wait for modal to disappear
|
||||
cy.waitUntil(() => cy.get('#editChannelHeaderModalLabel').should('not.be.visible'));
|
||||
}
|
||||
|
||||
function checkSystemMessage(message) {
|
||||
// * system message is posted notifying of the change
|
||||
cy.getLastPostId().then((id) => {
|
||||
cy.get(`#postMessageText_${id}`).should('contain', message);
|
||||
cy.clickPostDotMenu(id).then(() => {
|
||||
// * system message can be deleted
|
||||
cy.get(`#delete_post_${id}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// Stage: @prod
|
||||
// Group: @channels @multi_team_and_dm
|
||||
|
||||
describe('Join an open team from a direct message link', () => {
|
||||
let openTeam;
|
||||
let testUserInOpenTeam;
|
||||
let publicChannelInOpenTeam;
|
||||
|
||||
let secondTestTeam;
|
||||
let testUserOutsideOpenTeam;
|
||||
|
||||
before(() => {
|
||||
cy.apiCreateTeam('mmt452-second-team', 'mmt452-second-team', 'I', true).then(({team}) => {
|
||||
secondTestTeam = team;
|
||||
|
||||
// # Create test user in closed team
|
||||
cy.apiCreateUser().then(({user}) => {
|
||||
testUserOutsideOpenTeam = user;
|
||||
cy.apiAddUserToTeam(secondTestTeam.id, testUserOutsideOpenTeam.id);
|
||||
});
|
||||
});
|
||||
|
||||
cy.apiCreateTeam('mmt452-open-team', 'mmt452-open-team', 'O', true).then(({team}) => {
|
||||
openTeam = team;
|
||||
|
||||
// # Allow any user with an account on this server to join this team
|
||||
cy.apiPatchTeam(openTeam.id, {
|
||||
allow_open_invite: true,
|
||||
});
|
||||
|
||||
// # Create a public channel inside the open team
|
||||
cy.apiCreateChannel(openTeam.id, 'open-team-channel', 'open-team-channel').then(({channel}) => {
|
||||
publicChannelInOpenTeam = channel;
|
||||
});
|
||||
|
||||
// # Create test user
|
||||
cy.apiCreateUser().then(({user}) => {
|
||||
testUserInOpenTeam = user;
|
||||
|
||||
// # Add user to open team
|
||||
cy.apiAddUserToTeam(openTeam.id, testUserInOpenTeam.id);
|
||||
|
||||
// # Login as test user
|
||||
cy.apiLogin(testUserInOpenTeam);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T452 User with no teams should be able to join an open team from a link in direct messages', () => {
|
||||
// # View 'off-topic' channel
|
||||
cy.visit(`/${openTeam.name}/channels/${publicChannelInOpenTeam.name}`);
|
||||
|
||||
// * Expect channel title to match title passed in argument
|
||||
cy.get('#channelHeaderTitle').
|
||||
should('be.visible').
|
||||
and('contain.text', publicChannelInOpenTeam.display_name);
|
||||
|
||||
// # Copy full url to channel
|
||||
cy.url().then((publicChannelUrl) => {
|
||||
// # From the 'Direct Messages' menu, send the URL of the public channel to the user outside the team
|
||||
sendDirectMessageToUser(testUserOutsideOpenTeam, openTeam, publicChannelUrl);
|
||||
|
||||
// # Logout as test user
|
||||
cy.apiLogout();
|
||||
|
||||
// # Login as user outside team
|
||||
cy.apiLogin(testUserOutsideOpenTeam);
|
||||
|
||||
// # Reload the page to ensure the new session is active
|
||||
cy.reload();
|
||||
|
||||
// * Expect page to reload with new user session, username should display in the header
|
||||
cy.uiOpenUserMenu().findByText(`@${testUserOutsideOpenTeam.username}`);
|
||||
|
||||
// # Open direct message from the user in the open team (testUserInOpenTeam)
|
||||
cy.visit(`/${secondTestTeam.name}/messages/@${testUserInOpenTeam.username}`);
|
||||
|
||||
// * Expect channel title to contain the username (ensures we opened the right DM)
|
||||
cy.get('#channelHeaderTitle').
|
||||
should('be.visible').
|
||||
and('contain.text', `${testUserInOpenTeam.username}`);
|
||||
|
||||
// # Click on URL sent by the user in the open team
|
||||
cy.findByTestId('postContent').
|
||||
first().
|
||||
find('a.theme.markdown__link').
|
||||
should('have.attr', 'href', publicChannelUrl);
|
||||
cy.visit(publicChannelUrl);
|
||||
|
||||
// * Expect URL to equal what was sent to the user outside the team
|
||||
cy.url().should('equal', publicChannelUrl);
|
||||
});
|
||||
|
||||
// * Expect the current team's display name to match the open team's display name
|
||||
cy.uiGetLHSHeader().findByText(openTeam.display_name);
|
||||
|
||||
// * Expect channel title to match the display name of our previously created channel
|
||||
cy.get('#channelHeaderTitle').
|
||||
should('be.visible').
|
||||
and('contain.text', publicChannelInOpenTeam.display_name);
|
||||
});
|
||||
});
|
||||
|
||||
const sendDirectMessageToUser = (user, team, message) => {
|
||||
// # Open the the direct messages channel with the target user
|
||||
cy.visit(`/${team.name}/messages/@${user.username}`);
|
||||
|
||||
// * Expect the channel title to be the user's username
|
||||
// In the channel header, it seems there is a space after the username, justifying the use of contains.text instead of have.text
|
||||
cy.get('#channelHeaderTitle').should('be.visible').and('contain.text', user.username);
|
||||
|
||||
// # Type message and send it to the user
|
||||
cy.postMessage(message);
|
||||
};
|
||||
@@ -0,0 +1,140 @@
|
||||
// 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.
|
||||
// ***************************************************************
|
||||
|
||||
// Group: @channels @multi_team_and_dm
|
||||
|
||||
describe('Multi-user group messages', () => {
|
||||
let testUser;
|
||||
let testTeam;
|
||||
before(() => {
|
||||
// # Create a new team
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testUser = user;
|
||||
testTeam = team;
|
||||
|
||||
// # Add 10 users to the team
|
||||
Cypress._.times(10, () => createUserAndAddToTeam(testTeam));
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T463 Should not be able to create a group message with more than 8 users', () => {
|
||||
// # Login as test user
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Go to town-square channel
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open the 'Direct messages' dialog to create a new direct message
|
||||
cy.uiAddDirectMessage().click();
|
||||
|
||||
// # Add the maximum amount of users to a group message (7)
|
||||
addUsersToGMViaModal(7);
|
||||
|
||||
// * Check that the user count in the group message modal equals 7
|
||||
cy.get('.react-select__multi-value').should('have.length', 7);
|
||||
|
||||
expectCannotAddUsersMessage(0);
|
||||
|
||||
// # Try to add one more user
|
||||
addUsersToGMViaModal(1);
|
||||
|
||||
// * Check that the list of users in the multi-select is still 7
|
||||
cy.get('.react-select__multi-value').should('have.length', 7);
|
||||
|
||||
// # Click on "Go" in the group message's dialog to begin the conversation
|
||||
cy.get('#saveItems').click();
|
||||
|
||||
// * Check that the number of users in the group message is 8
|
||||
cy.get('#channelMemberCountText').
|
||||
should('be.visible').
|
||||
and('have.text', '8');
|
||||
|
||||
// * Check that the direct message text input's placeholder is truncated if the user's list is too long
|
||||
cy.get('[data-testid="post_textbox_placeholder"]').
|
||||
should('be.visible').
|
||||
and('have.css', 'overflow', 'hidden').
|
||||
and('have.css', 'text-overflow', 'ellipsis');
|
||||
|
||||
// # From the group message's window, click on the user list's dropdown
|
||||
cy.get('#channelHeaderTitle').click();
|
||||
|
||||
// # From the dropdown menu, click on "Add members"
|
||||
cy.get('#channelMembers').click();
|
||||
cy.uiGetButton('Add').click();
|
||||
|
||||
// # Try to add one more user from the group message's list
|
||||
addUsersToGMViaModal(1);
|
||||
|
||||
// # Check that the appropriate information & warnings are displayed in the group message's dialog
|
||||
expectCannotAddUsersMessage(0);
|
||||
|
||||
// * Check that the count of selected number of users in the group message's dialog is 7
|
||||
cy.get('.react-select__multi-value').
|
||||
should('be.visible').
|
||||
and('have.length', 7);
|
||||
|
||||
// # Remove the last user from the group message's dialog input section
|
||||
cy.get('.react-select__multi-value__remove').
|
||||
should('be.visible').
|
||||
and('have.length', 7).
|
||||
last().
|
||||
click();
|
||||
|
||||
// # Check that the appropriate information & warnings are displayed in the group message's dialog
|
||||
expectCannotAddUsersMessage(1);
|
||||
});
|
||||
});
|
||||
|
||||
// Helper functions
|
||||
|
||||
const createUserAndAddToTeam = (team) => {
|
||||
cy.apiCreateUser({prefix: 'gm'}).then(({user}) =>
|
||||
cy.apiAddUserToTeam(team.id, user.id),
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a given amount of numbers to a direct message group
|
||||
* @param {number} userCountToAdd
|
||||
*/
|
||||
const addUsersToGMViaModal = (userCountToAdd) => {
|
||||
// # Ensure there are enough selectable users in the list
|
||||
cy.get('#multiSelectList').
|
||||
should('be.visible').
|
||||
children().
|
||||
should('have.length.gte', userCountToAdd);
|
||||
|
||||
// # Add the first user from the top of the list, as many times as requested by 'userCountToAdd'
|
||||
Cypress._.times(userCountToAdd, () => {
|
||||
cy.get('#multiSelectList').
|
||||
children().
|
||||
first().
|
||||
click();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* In the "Direct messages" dialog, assert against help section that appropriate messages are displayed
|
||||
* - The number of people that still can be added to the group message
|
||||
* - The information message advising to start a private channel when the maximum number of users is reached (if applicable)
|
||||
* @param {number} expectedUsersLeftToAdd
|
||||
*/
|
||||
const expectCannotAddUsersMessage = (expectedUsersLeftToAdd) => {
|
||||
const maxUsersGMNote = "You've reached the maximum number of people for this conversation. Consider creating a private channel instead.";
|
||||
|
||||
// * Check that the help section indicates we cannot add anymore users
|
||||
cy.get('#multiSelectHelpMemberInfo').
|
||||
should('be.visible').
|
||||
and('contain.text', `You can add ${expectedUsersLeftToAdd} more ${expectedUsersLeftToAdd === 1 ? 'person' : 'people'}`);
|
||||
|
||||
if (expectedUsersLeftToAdd === 0) {
|
||||
// * Check that a note in the help section suggests creating a private channel instead
|
||||
cy.get('#multiSelectMessageNote').should('contain.text', maxUsersGMNote);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
// 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 @multi_team_and_dm
|
||||
|
||||
import {DEFAULT_TEAM} from '@/support/constants';
|
||||
|
||||
const NUMBER_OF_TEAMS = 3;
|
||||
|
||||
describe('Multi-Team + DMs', () => {
|
||||
before(() => {
|
||||
// # Create an account
|
||||
cy.apiCreateUser().its('user').as('user');
|
||||
|
||||
// # Delete all existing teams to clean-up
|
||||
cy.apiGetAllTeams().then(({teams}) => {
|
||||
teams.forEach((team) => {
|
||||
if (team.name !== DEFAULT_TEAM.name) {
|
||||
cy.apiDeleteTeam(team.id, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// # Create teams for user to join
|
||||
for (let i = 0; i < NUMBER_OF_TEAMS; i++) {
|
||||
cy.apiCreateTeam('team', 'Team', 'O', true, {allow_open_invite: true});
|
||||
}
|
||||
});
|
||||
|
||||
it('MM-T1805 No infinite loading spinner on Select Team page', function() {
|
||||
// # Log-in with created user
|
||||
cy.apiLogin(this.user);
|
||||
|
||||
// # Join all available teams and go to {servername}/select_team
|
||||
joinAllTeams();
|
||||
|
||||
// * Check that no infinite loading spinner is shown
|
||||
cy.get('.loading-screen').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
function joinAllTeams() {
|
||||
cy.visit('/select_team');
|
||||
cy.findByText('All team communication in one place, searchable and accessible anywhere');
|
||||
cy.findAllByText(/Team\s/).then(([firstTeam, nextTeam]) => {
|
||||
firstTeam.click();
|
||||
|
||||
if (nextTeam) {
|
||||
joinAllTeams();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// 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 @multi_team_and_dm
|
||||
|
||||
import * as TIMEOUTS from '@/fixtures/timeouts';
|
||||
import * as MESSAGES from '@/fixtures/messages';
|
||||
|
||||
describe('Send a DM', () => {
|
||||
let userA;
|
||||
let userB;
|
||||
let team1;
|
||||
let testChannelUrl;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
userA = user;
|
||||
team1 = team;
|
||||
testChannelUrl = `/${team.name}/channels/town-square`;
|
||||
|
||||
cy.apiCreateUser().then(({user: otherUser}) => {
|
||||
userB = otherUser;
|
||||
cy.apiAddUserToTeam(team.id, userB.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T451 Send a DM to someone on no team', () => {
|
||||
// # Log in as UserA and leave all teams
|
||||
cy.apiLogin(userA);
|
||||
cy.visit(testChannelUrl);
|
||||
cy.get('#postListContent', {timeout: TIMEOUTS.HALF_MIN}).should('be.visible');
|
||||
cy.uiGetLHSHeader().click();
|
||||
cy.findByText('Leave team').click();
|
||||
cy.findByText('Yes').click();
|
||||
cy.url().should('include', '/select_team');
|
||||
|
||||
// # Log in as User B and send User A a direct message
|
||||
cy.apiLogout();
|
||||
cy.apiLogin(userB);
|
||||
cy.visit(testChannelUrl);
|
||||
cy.uiAddDirectMessage().click();
|
||||
cy.get('#selectItems input').typeWithForce(userA.username).wait(TIMEOUTS.HALF_SEC);
|
||||
cy.get('#multiSelectList').findByText(`@${userA.username}`).click();
|
||||
cy.findByText('Go').click();
|
||||
cy.postMessage(MESSAGES.SMALL);
|
||||
|
||||
// * From User B's perspective, message sends.
|
||||
cy.uiWaitUntilMessagePostedIncludes(MESSAGES.SMALL);
|
||||
|
||||
// * The DM appears in your LHS / channel drawer even though other user isn't on any teams
|
||||
cy.uiGetLhsSection('DIRECT MESSAGES').findByText(userA.username).should('be.visible');
|
||||
|
||||
// # Have User A re-join one of the teams
|
||||
cy.apiAddUserToTeam(team1.id, userA.id);
|
||||
|
||||
// * After User A rejoins a team, the DM channel is visible to them in their LHS / channel drawer
|
||||
cy.apiLogout();
|
||||
cy.apiLogin(userA);
|
||||
cy.visit(testChannelUrl);
|
||||
cy.get('#postListContent', {timeout: TIMEOUTS.TWO_MIN}).should('be.visible');
|
||||
cy.uiGetLhsSection('DIRECT MESSAGES').findByText(userB.username).should('be.visible');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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 @multi_team_and_dm
|
||||
|
||||
describe('Multi Team and DM', () => {
|
||||
let testChannel;
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let otherUser;
|
||||
|
||||
before(() => {
|
||||
// # Setup with the new team, channel and user
|
||||
cy.apiInitSetup().then(({team, channel, user}) => {
|
||||
testTeam = team;
|
||||
testChannel = channel;
|
||||
testUser = user;
|
||||
|
||||
// # Create otherUser
|
||||
cy.apiCreateUser().then(({user: user2}) => {
|
||||
otherUser = user2;
|
||||
});
|
||||
|
||||
// # Login with testUser and visit test channel
|
||||
cy.apiLogin(testUser);
|
||||
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T439 Town Square is not marked as unread for existing users when a new user is added to the team', () => {
|
||||
// # Open 'Advanced' section of 'Settings' modal
|
||||
cy.uiOpenSettingsModal('Advanced').within(() => {
|
||||
// # Open 'Enable Join/Leave Messages' and turn it off
|
||||
cy.findByRole('heading', {name: 'Enable Join/Leave Messages'}).click();
|
||||
cy.findByRole('radio', {name: 'Off'}).click();
|
||||
|
||||
// # Save and close the modal
|
||||
cy.uiSaveAndClose();
|
||||
});
|
||||
|
||||
// # Confirm Town Square is marked as read
|
||||
cy.findByLabelText('town square public channel').should('be.visible');
|
||||
|
||||
// # Remove focus from Town Square
|
||||
cy.findByLabelText('off-topic public channel').click();
|
||||
|
||||
// # Add second user to team in external session
|
||||
cy.externalAddUserToTeam(otherUser.id, testTeam.id);
|
||||
|
||||
// * Assert that Town Square is still marked as read after second user added to team
|
||||
cy.findByLabelText('town square public channel').should('be.visible');
|
||||
|
||||
// * Switch to different channel and assert that Town Square is still marked as read
|
||||
cy.findByText(testChannel.display_name).click();
|
||||
cy.findByLabelText('town square public channel').should('not.have.css', 'font-weight', '600');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user