391 строка
16 KiB
JavaScript
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();
|
|
});
|
|
};
|