Files

391 строка
16 KiB
JavaScript

// 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)
// ***************************************************************
// Stage: @prod
// Group: @playbooks
describe('channels > broadcast', {testIsolation: true}, () => {
let testTeam;
let testUser;
let testAdmin;
let testPublicChannel1;
let testPublicChannel2;
let testPrivateChannel1;
let testPrivateChannel2;
let publicBroadcastPlaybook;
let privateBroadcastPlaybook;
let allBroadcastPlaybook;
let rootDeletePlaybook;
before(() => {
cy.apiInitSetup().then(({team, user}) => {
testTeam = team;
testUser = user;
cy.apiCreateCustomAdmin().then(({sysadmin: adminUser}) => {
testAdmin = adminUser;
cy.apiAddUserToTeam(testTeam.id, adminUser.id);
cy.apiSaveJoinLeaveMessagesPreference(adminUser.id, false);
// # Login as testUser
cy.apiLogin(testUser);
// # Create a public channel
cy.apiCreateChannel(
testTeam.id,
'public-channel',
'Public Channel 1',
'O',
).then(({channel: publicChannel1}) => {
testPublicChannel1 = publicChannel1;
// # Create a public channel
cy.apiCreateChannel(
testTeam.id,
'public-channel',
'Public Channel 2',
'O',
).then(({channel: publicChannel2}) => {
testPublicChannel2 = publicChannel2;
// # Create a private channel
cy.apiCreateChannel(
testTeam.id,
'private-channel',
'Private Channel 1',
'P',
).then(({channel: privateChannel1}) => {
testPrivateChannel1 = privateChannel1;
// # Create a private channel
cy.apiCreateChannel(
testTeam.id,
'private-channel',
'Private Channel 2',
'P',
).then(({channel: privateChannel2}) => {
testPrivateChannel2 = privateChannel2;
// # Create a playbook that will broadcast to public channel1
cy.apiCreateTestPlaybook({
teamId: testTeam.id,
title: 'Playbook - public broadcast',
userId: testUser.id,
broadcastChannelIds: [testPublicChannel1.id],
broadcastEnabled: true,
}).then((playbook) => {
publicBroadcastPlaybook = playbook;
});
// # Create a playbook that will broadcast to private channel1
cy.apiCreateTestPlaybook({
teamId: testTeam.id,
title: 'Playbook - private broadcast',
userId: testUser.id,
broadcastChannelIds: [testPrivateChannel1.id],
broadcastEnabled: true,
}).then((playbook) => {
privateBroadcastPlaybook = playbook;
});
// # Create a playbook that will broadcast to all 4 channels
cy.apiCreateTestPlaybook({
teamId: testTeam.id,
title: 'Playbook - public and private broadcast',
userId: testUser.id,
broadcastChannelIds: [testPublicChannel1.id, testPublicChannel2.id, testPrivateChannel1.id, testPrivateChannel2.id],
broadcastEnabled: true,
}).then((playbook) => {
allBroadcastPlaybook = playbook;
});
// # Create a playbook for testing deleting root posts
cy.apiCreateTestPlaybook({
teamId: testTeam.id,
title: 'Playbook - test deleting root posts',
userId: testUser.id,
broadcastChannelIds: [testPublicChannel1.id, testPrivateChannel1.id],
broadcastEnabled: true,
otherMembers: [testAdmin.id],
invitedUserIds: [testAdmin.id],
}).then((playbook) => {
rootDeletePlaybook = playbook;
});
// # invite testAdmin to the channel they will need to be in to delete the post
cy.apiAddUserToChannel(testPublicChannel1.id, testAdmin.id);
cy.apiAddUserToChannel(testPrivateChannel1.id, testAdmin.id);
});
});
});
});
});
});
});
beforeEach(() => {
// # Login as testUser
cy.apiLogin(testUser);
// # Size the viewport to show the RHS without covering posts.
cy.viewport('macbook-13');
// # Go to Town Square
cy.visit(`/${testTeam.name}/channels/town-square`);
});
it('to public channels', () => {
// # Create a new playbook run
const now = Date.now();
const playbookRunName = `Playbook Run (${now})`;
const playbookRunChannelName = `playbook-run-${now}`;
cy.apiRunPlaybook({
teamId: testTeam.id,
playbookId: publicBroadcastPlaybook.id,
playbookRunName,
ownerUserId: testUser.id,
});
// # Navigate directly to the application and the playbook run channel
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
// # Update the playbook run's status
const updateMessage = 'Update - ' + now;
cy.updateStatus(updateMessage);
// * Verify the posts
const initialMessage = playbookRunName;
verifyInitialAndStatusPostInBroadcast(testTeam, testPublicChannel1.name, playbookRunName, initialMessage, updateMessage);
});
it('does not broadcast when broadcast is disabled, even if broadcastChannelIds contain data', () => {
// # Create a brand new channel
cy.apiCreateChannel(
testTeam.id,
'public-channel-do-not-broadcast',
'Public Channel 1 - do not broadcast',
'O',
).then(({channel}) => {
// # Create a playbook with broadcast disabled, but with broadcastChannelIds containing channel1
cy.apiCreateTestPlaybook({
teamId: testTeam.id,
title: 'Playbook - disabled public broadcast',
userId: testUser.id,
broadcastChannelIds: [channel.id],
broadcastEnabled: false,
}).then((playbook) => {
// # Create a new playbook run with that playbook
const now = Date.now();
const playbookRunName = `Playbook Run (${now})`;
const playbookRunChannelName = `playbook-run-${now}`;
cy.apiRunPlaybook({
teamId: testTeam.id,
playbookId: playbook.id,
playbookRunName,
ownerUserId: testUser.id,
});
// # Navigate directly to the application and the playbook run channel
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
// # Update the playbook run's status
const updateMessage = 'Update - ' + now;
cy.updateStatus(updateMessage);
// # Navigate to the broadcast channel
cy.visit(`/${testTeam.name}/channels/${channel.name}`);
// * Verify that the last post is the system post containing the join message,
// so no announcement nor update was posted
cy.getLastPostId().then((lastPostId) => {
cy.get(`#postMessageText_${lastPostId}`).contains('You joined the channel');
});
});
});
});
it('to private channels', () => {
// # Create a new playbook run
const now = Date.now();
const playbookRunName = 'Playbook Run (' + now + ')';
const playbookRunChannelName = 'playbook-run-' + now;
cy.apiRunPlaybook({
teamId: testTeam.id,
playbookId: privateBroadcastPlaybook.id,
playbookRunName,
ownerUserId: testUser.id,
});
// # Navigate directly to the application and the playbook run channel
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
// # Update the playbook run's status
const updateMessage = 'Update - ' + now;
cy.updateStatus(updateMessage);
// * Verify the posts
const initialMessage = playbookRunName;
verifyInitialAndStatusPostInBroadcast(testTeam, testPrivateChannel1.name, playbookRunName, initialMessage, updateMessage);
});
it('to 4 public and private channels', () => {
// # Create a new playbook run
const now = Date.now();
const playbookRunName = 'Playbook Run (' + now + ')';
const playbookRunChannelName = 'playbook-run-' + now;
cy.apiRunPlaybook({
teamId: testTeam.id,
playbookId: allBroadcastPlaybook.id,
playbookRunName,
ownerUserId: testUser.id,
});
// # Navigate directly to the application and the playbook run channel
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
// # Update the playbook run's status
const updateMessage = 'Update - ' + now;
cy.updateStatus(updateMessage, 0);
// * Verify the posts
const initialMessage = playbookRunName;
verifyInitialAndStatusPostInBroadcast(testTeam, testPublicChannel1.name, playbookRunName, initialMessage, updateMessage);
verifyInitialAndStatusPostInBroadcast(testTeam, testPrivateChannel1.name, playbookRunName, initialMessage, updateMessage);
verifyInitialAndStatusPostInBroadcast(testTeam, testPublicChannel2.name, playbookRunName, initialMessage, updateMessage);
verifyInitialAndStatusPostInBroadcast(testTeam, testPrivateChannel2.name, playbookRunName, initialMessage, updateMessage);
});
it('to 2 channels, delete the root post, update again', () => {
// # Create a new playbook run
const now = Date.now();
const playbookRunName = 'Playbook Run (' + now + ')';
const playbookRunChannelName = 'playbook-run-' + now;
cy.apiRunPlaybook({
teamId: testTeam.id,
playbookId: rootDeletePlaybook.id,
playbookRunName,
ownerUserId: testUser.id,
});
// # Navigate directly to the application and the playbook run channel
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
// # Update the playbook run's status
const updateMessage = 'Update - ' + now;
cy.updateStatus(updateMessage, 0);
// * Verify the posts
const initialMessage = playbookRunName;
verifyInitialAndStatusPostInBroadcast(testTeam, testPublicChannel1.name, playbookRunName, initialMessage, updateMessage);
verifyInitialAndStatusPostInBroadcast(testTeam, testPrivateChannel1.name, playbookRunName, initialMessage, updateMessage);
// # need to be admin to delete the bot's posts
cy.apiLogin(testAdmin);
// # Delete both root posts
deleteLatestPostRoot(testTeam, testPublicChannel1.name);
deleteLatestPostRoot(testTeam, testPrivateChannel1.name);
// # Log back in as testUser
cy.apiLogin(testUser);
// # Make two more updates
// # Navigate directly to the application and the playbook run channel
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
// # Update the playbook run's status twice
const updateMessage2 = updateMessage + ' - 2';
cy.updateStatus(updateMessage2, 0);
const updateMessage3 = updateMessage + ' - 3';
cy.updateStatus(updateMessage3, 0);
// * Verify the posts
verifyInitialAndStatusPostInBroadcast(testTeam, testPublicChannel1.name, playbookRunName, updateMessage2, updateMessage3);
verifyInitialAndStatusPostInBroadcast(testTeam, testPrivateChannel1.name, playbookRunName, updateMessage2, updateMessage3);
});
});
const verifyInitialAndStatusPostInBroadcast = (testTeam, channelName, runName, initialMessage, updateMessage) => {
cy.log(`Verifying initial and status post in broadcast (channel ${channelName}, run ${runName})`);
// # Navigate to the broadcast channel
cy.visit(`/${testTeam.name}/channels/${channelName}`);
// * Verify that the last post contains the expected header and the update message verbatim
cy.getLastPostId().then((lastPostId) => {
// # Open RHS comment menu
cy.clickPostCommentIcon(lastPostId);
cy.get('#rhsContainer').
should('exist').
within(() => {
// * Thread should have two posts
cy.findAllByTestId('postContent').should('have.length', 2);
// * The first should be announcement
cy.findAllByTestId('postContent').eq(0).contains(initialMessage);
// * Latest post should be update
cy.get(`#rhsPost_${lastPostId}`).contains(
`posted an update for ${runName}`,
);
cy.get(`#rhsPost_${lastPostId}`).contains('tasks checked');
cy.get(`#rhsPost_${lastPostId}`).contains('participant');
cy.get(`#rhsPost_${lastPostId}`).contains(updateMessage);
});
});
};
const deleteLatestPostRoot = (testTeam, channelName) => {
cy.log(`Deleting latest root post (channel ${channelName})`);
// # Navigate to the channel
cy.visit(`/${testTeam.name}/channels/${channelName}`);
cy.getLastPostId().then((lastPostId) => {
// # Open RHS comment menu
cy.clickPostCommentIcon(lastPostId);
cy.get('#rhsContainer').
should('exist').
within(() => {
cy.findAllByTestId('postContent').eq(0).parent().then((root) => {
const rootId = root.attr('id').slice(8);
// # Click root's post dot menu.
cy.clickPostDotMenu(rootId, 'RHS_ROOT');
// # Click delete button.
const id = `#delete_post_${rootId}`;
cy.wrap(id).as('deleteId');
});
});
// * Post extra options is visible
cy.findByLabelText('Post extra options').should('exist');
// # Click delete button.
cy.get('@deleteId').then((deleteId) => {
cy.get(deleteId).should('be.visible').click();
});
// * Check that confirmation dialog is open.
cy.get('#deletePostModal').should('be.visible');
// * Check that confirmation dialog contains correct text
cy.get('#deletePostModal').
should('contain', 'Are you sure you want to delete this message?');
// * Check that confirmation dialog shows that the post has one comment on it
cy.get('#deletePostModal').should('contain', 'This message has 1 comment on it.');
// # Confirm deletion.
cy.get('#deletePostModalButton').click();
});
};