Move /e2e -> /e2e-tests
Этот коммит содержится в:
@@ -0,0 +1,558 @@
|
||||
// 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
|
||||
|
||||
import {switchToChannel} from '../../../channels/mark_as_unread/helpers';
|
||||
|
||||
describe('channels > slash command > owner', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
let testPlaybook;
|
||||
let playbookRunName;
|
||||
let playbookRunChannelName;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiCreateUser().then(({user: user2}) => {
|
||||
testUser2 = user2;
|
||||
cy.apiAddUserToTeam(testTeam.id, testUser2.id);
|
||||
});
|
||||
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook',
|
||||
checklists: [
|
||||
{
|
||||
title: 'Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
],
|
||||
memberIDs: [testUser.id],
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
const now = Date.now();
|
||||
playbookRunName = `Playbook Run (${now})`;
|
||||
playbookRunChannelName = `playbook-run-${now}`;
|
||||
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName,
|
||||
ownerUserId: testUser.id,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
});
|
||||
|
||||
describe('single run channel', () => {
|
||||
it('check', () => {
|
||||
// # Type a command
|
||||
cy.findByTestId('post_textbox').clear().type('/playbook check ');
|
||||
|
||||
// * Verify suggestions number: a single run with 4 tasks + 1 title
|
||||
cy.get('.slash-command').should('have.length', 5);
|
||||
|
||||
// # Clear input
|
||||
cy.findByTestId('post_textbox').clear();
|
||||
|
||||
// # Run a slash command with correct parameters
|
||||
cy.uiPostMessageQuickly('/playbook check 1 1');
|
||||
|
||||
// * Verify the task is checked
|
||||
cy.get('[data-rbd-droppable-id="1"]').find('.checkbox').eq(1).should('be.checked');
|
||||
});
|
||||
|
||||
it('check add', () => {
|
||||
// # Run a slash command with correct parameters
|
||||
cy.uiPostMessageQuickly('/playbook checkadd 1 new-task');
|
||||
|
||||
// * Verify the task was added
|
||||
cy.get('[data-rbd-droppable-id="1"]').contains('new-task');
|
||||
});
|
||||
|
||||
it('check remove', () => {
|
||||
// # Run a slash command with correct parameters
|
||||
cy.uiPostMessageQuickly('/playbook checkremove 1 1');
|
||||
|
||||
// * Verify the task was added
|
||||
cy.get('[data-rbd-droppable-id="1"]').contains('Step 2').should('not.exist');
|
||||
});
|
||||
|
||||
it('owner', () => {
|
||||
// # Run a slash command
|
||||
cy.uiPostMessageQuickly('/playbook owner');
|
||||
|
||||
// * Verify the message.
|
||||
cy.verifyEphemeralMessage(`@${testUser.username} is the current owner for this playbook run.`);
|
||||
|
||||
// # Run a slash command
|
||||
cy.uiPostMessageQuickly(`/playbook owner @${testUser2.username}`);
|
||||
|
||||
// * Verify that the owner was set.
|
||||
cy.uiPostMessageQuickly('/playbook owner');
|
||||
cy.verifyEphemeralMessage(`@${testUser2.username} is the current owner for this playbook run.`);
|
||||
});
|
||||
|
||||
it('timeline', () => {
|
||||
// # Run a slash command on a run with view access
|
||||
cy.uiPostMessageQuickly('/playbook timeline');
|
||||
|
||||
// * Verify the message.
|
||||
cy.verifyEphemeralMessage(`Timeline for ${playbookRunName}`);
|
||||
});
|
||||
|
||||
it('finish', () => {
|
||||
// # Run a slash command with correct parameters
|
||||
cy.uiPostMessageQuickly('/playbook finish');
|
||||
|
||||
// * Verify confirm modal is visible.
|
||||
cy.get('#interactiveDialogModalLabel').should('exist');
|
||||
|
||||
// # Confirm finish
|
||||
cy.get('#interactiveDialogSubmit').click();
|
||||
|
||||
// * Verify that the run is finished.
|
||||
cy.get('#rhsContainer').findByTestId('badge').contains('Finished');
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiple runs in the channel', () => {
|
||||
let playbookRuns;
|
||||
let testPrivatePlaybook;
|
||||
let testPublicPlaybook;
|
||||
let testPublicChannel;
|
||||
let channelName;
|
||||
|
||||
before(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create private playbook, channel mode set to link existing channel
|
||||
cy.apiCreatePlaybook({
|
||||
makePublic: false,
|
||||
createPublicPlaybookRun: false,
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook private',
|
||||
checklists: [
|
||||
{
|
||||
title: 'Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
],
|
||||
memberIDs: [testUser.id],
|
||||
channelMode: 'link_existing_channel',
|
||||
}).then((playbook) => {
|
||||
testPrivatePlaybook = playbook;
|
||||
});
|
||||
|
||||
// # Create public playbook, channel mode set to link existing channel
|
||||
cy.apiCreatePlaybook({
|
||||
makePublic: true,
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook public',
|
||||
checklists: [
|
||||
{
|
||||
title: 'Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
],
|
||||
memberIDs: [testUser.id],
|
||||
channelMode: 'link_existing_channel',
|
||||
}).then((playbook) => {
|
||||
testPublicPlaybook = playbook;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
playbookRuns = [];
|
||||
const now = Date.now();
|
||||
channelName = 'public-channel-' + now;
|
||||
|
||||
// # Create channel for runs
|
||||
cy.apiCreateChannel(
|
||||
testTeam.id,
|
||||
channelName,
|
||||
'public channel',
|
||||
'O',
|
||||
).then(({channel: publicChannel}) => {
|
||||
testPublicChannel = publicChannel;
|
||||
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPrivatePlaybook.id,
|
||||
playbookRunName: 'run write access ' + now,
|
||||
ownerUserId: testUser.id,
|
||||
channelId: testPublicChannel.id,
|
||||
}).then((playbookRun) => {
|
||||
cy.apiAddUsersToRun(playbookRun.id, [testUser2.id]);// add test user to participants list
|
||||
playbookRuns.push(playbookRun);
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPublicPlaybook.id,
|
||||
playbookRunName: 'run view access' + now,
|
||||
ownerUserId: testUser.id,
|
||||
channelId: testPublicChannel.id,
|
||||
}).then((playbookRun2) => {
|
||||
playbookRuns.push(playbookRun2);
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPrivatePlaybook.id,
|
||||
playbookRunName: 'run no access' + now,
|
||||
ownerUserId: testUser.id,
|
||||
channelId: testPublicChannel.id,
|
||||
}).then((playbookRun3) => {
|
||||
playbookRuns.push(playbookRun3);
|
||||
|
||||
// # Add testUser2 to the channel
|
||||
cy.apiAddUserToChannel(testPublicChannel.id, testUser2.id);
|
||||
|
||||
// # Login as testUser2
|
||||
cy.apiLogin(testUser2);
|
||||
|
||||
// # Navigate directly to the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${testPublicChannel.name}`);
|
||||
switchToChannel(testPublicChannel);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('check', () => {
|
||||
// # Run a slash command with not enough parameters
|
||||
cy.uiPostMessageQuickly('/playbook check 1 1');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Command expects three arguments: the run number, the checklist number and the item number.');
|
||||
|
||||
// # Run a slash command wrong run number
|
||||
cy.uiPostMessageQuickly('/playbook check 2 1 1');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Invalid run number');
|
||||
|
||||
// # Run a slash command on a run with view access
|
||||
cy.uiPostMessageQuickly('/playbook check 0 1 1');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Become a participant to interact with this run');
|
||||
|
||||
// # Type a command
|
||||
cy.findByTestId('post_textbox').clear().type('/playbook check ');
|
||||
|
||||
// * Verify suggestions number: 2 runs * 4 tasks + 1 title
|
||||
cy.get('.slash-command').should('have.length', 9);
|
||||
|
||||
// # Clear input
|
||||
cy.findByTestId('post_textbox').clear();
|
||||
|
||||
// # Run a slash command with correct parameters
|
||||
cy.uiPostMessageQuickly('/playbook check 1 1 1');
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
// * Verify number of runs
|
||||
cy.get('[data-testid="run-list-card"]').should('have.length', 2);
|
||||
|
||||
// # Open run details view
|
||||
cy.findByText(playbookRuns[0].name).click({force: true});
|
||||
});
|
||||
|
||||
// * Verify the task is checked
|
||||
cy.get('[data-rbd-droppable-id="1"]').find('.checkbox').eq(1).should('be.checked');
|
||||
});
|
||||
|
||||
it('check add', () => {
|
||||
// # Run a slash command with not enough parameters
|
||||
cy.uiPostMessageQuickly('/playbook checkadd 1');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Command expects two arguments: the run number and the checklist number.');
|
||||
|
||||
// # Run a slash command wrong run number
|
||||
cy.uiPostMessageQuickly('/playbook checkadd 2 1 1');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Invalid run number');
|
||||
|
||||
// # Run a slash command on a run with view access
|
||||
cy.uiPostMessageQuickly('/playbook checkadd 0 1 new-task');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Become a participant to interact with this run');
|
||||
|
||||
// # Type a command
|
||||
cy.findByTestId('post_textbox').clear().type('/playbook checkadd ');
|
||||
|
||||
// * Verify suggestions number: 2 runs * 2 checklists + 1 title
|
||||
cy.get('.slash-command').should('have.length', 5);
|
||||
|
||||
// # Clear input
|
||||
cy.findByTestId('post_textbox').clear();
|
||||
|
||||
// # Run a slash command with correct parameters
|
||||
cy.uiPostMessageQuickly('/playbook checkadd 1 1 new-task');
|
||||
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
// * Verify number of runs
|
||||
cy.get('[data-testid="run-list-card"]').should('have.length', 2);
|
||||
|
||||
// # Open run details view
|
||||
cy.findByText(playbookRuns[0].name).click({force: true});
|
||||
});
|
||||
|
||||
// * Verify the task was added
|
||||
cy.get('[data-rbd-droppable-id="1"]').contains('new-task');
|
||||
});
|
||||
|
||||
it('check remove', () => {
|
||||
// # Run a slash command with not enough parameters
|
||||
cy.uiPostMessageQuickly('/playbook checkremove 1 1');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Command expects three arguments: the run number, the checklist number and the item number.');
|
||||
|
||||
// # Run a slash command wrong run number
|
||||
cy.uiPostMessageQuickly('/playbook checkremove 2 0 1');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Invalid run number');
|
||||
|
||||
// # Run a slash command on a run with view access
|
||||
cy.uiPostMessageQuickly('/playbook checkremove 0 1 0');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Become a participant to interact with this run');
|
||||
|
||||
// # Type a command
|
||||
cy.findByTestId('post_textbox').clear().type('/playbook checkremove ');
|
||||
|
||||
// * Verify suggestions number: 2 runs * 4 tasks + 1 title
|
||||
cy.get('.slash-command').should('have.length', 9);
|
||||
|
||||
// # Clear input
|
||||
cy.findByTestId('post_textbox').clear();
|
||||
|
||||
// # Run a slash command with correct parameters
|
||||
cy.uiPostMessageQuickly('/playbook checkremove 1 1 1');
|
||||
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
// * Verify number of runs
|
||||
cy.get('[data-testid="run-list-card"]').should('have.length', 2);
|
||||
|
||||
// # Open run details view
|
||||
cy.findByText(playbookRuns[0].name).click({force: true});
|
||||
});
|
||||
|
||||
// * Verify the task was added
|
||||
cy.get('[data-rbd-droppable-id="1"]').contains('Step 2').should('not.exist');
|
||||
});
|
||||
|
||||
it('owner', () => {
|
||||
// # Run a slash command with not enough parameters
|
||||
cy.uiPostMessageQuickly('/playbook owner');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('/playbook owner expects at most one argument.');
|
||||
|
||||
// # Run a slash command wrong run number
|
||||
cy.uiPostMessageQuickly('/playbook owner 2');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Invalid run number');
|
||||
|
||||
// # Run a slash command on a run with view access
|
||||
cy.uiPostMessageQuickly('/playbook owner 0');
|
||||
|
||||
// * Verify the message.
|
||||
cy.verifyEphemeralMessage(`@${testUser.username} is the current owner for this playbook run.`);
|
||||
|
||||
// # Type a command
|
||||
cy.findByTestId('post_textbox').clear().type('/playbook owner ');
|
||||
|
||||
// * Verify suggestions number: 2 runs + 1 title
|
||||
cy.get('.slash-command').should('have.length', 3);
|
||||
|
||||
// # Clear input
|
||||
cy.findByTestId('post_textbox').clear();
|
||||
|
||||
// # Run a slash command on a run with view access
|
||||
cy.uiPostMessageQuickly(`/playbook owner 0 @${testUser2.username}`);
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Become a participant to interact with this run');
|
||||
|
||||
// # Run a slash command on a run with write access
|
||||
cy.uiPostMessageQuickly(`/playbook owner 1 @${testUser2.username}`);
|
||||
|
||||
// * Verify that the owner was set.
|
||||
cy.uiPostMessageQuickly('/playbook owner 1');
|
||||
cy.verifyEphemeralMessage(`@${testUser2.username} is the current owner for this playbook run.`);
|
||||
});
|
||||
|
||||
it('finish', () => {
|
||||
// # Run a slash command with not enough parameters
|
||||
cy.uiPostMessageQuickly('/playbook finish');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Command expects one argument: the run number.');
|
||||
|
||||
// # Run a slash command wrong run number
|
||||
cy.uiPostMessageQuickly('/playbook finish 2');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Invalid run number');
|
||||
|
||||
// # Run a slash command on a run with view access
|
||||
cy.uiPostMessageQuickly('/playbook finish 0');
|
||||
|
||||
// * Verify the message.
|
||||
cy.verifyEphemeralMessage(`userID ${testUser2.id} is not an admin or channel member`);
|
||||
|
||||
// # Type a command
|
||||
cy.findByTestId('post_textbox').clear().type('/playbook finish ');
|
||||
|
||||
// * Verify suggestions number: 2 runs + 1 title
|
||||
cy.get('.slash-command').should('have.length', 3);
|
||||
|
||||
// # Clear input
|
||||
cy.findByTestId('post_textbox').clear();
|
||||
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
// * Verify number of runs
|
||||
cy.get('[data-testid="run-list-card"]').should('have.length', 2);
|
||||
|
||||
// # Open run details view
|
||||
cy.findByText(playbookRuns[0].name).click({force: true});
|
||||
});
|
||||
|
||||
// # Run a slash command with correct parameters
|
||||
cy.uiPostMessageQuickly('/playbook finish 1');
|
||||
|
||||
// * Verify confirm modal is visible.
|
||||
cy.get('#interactiveDialogModalLabel').should('exist');
|
||||
|
||||
// # Confirm finish
|
||||
cy.get('#interactiveDialogSubmit').click();
|
||||
|
||||
// * Verify that the run is finished.
|
||||
cy.get('#rhsContainer').findByTestId('badge').contains('Finished');
|
||||
});
|
||||
|
||||
it('timeline', () => {
|
||||
// # Run a slash command with not enough parameters
|
||||
cy.uiPostMessageQuickly('/playbook timeline');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Command expects one argument: the run number.');
|
||||
|
||||
// # Run a slash command wrong run number
|
||||
cy.uiPostMessageQuickly('/playbook timeline 2');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Invalid run number');
|
||||
|
||||
// # Run a slash command on a run with view access
|
||||
cy.uiPostMessageQuickly('/playbook timeline 0');
|
||||
|
||||
// * Verify the message.
|
||||
cy.verifyEphemeralMessage(`Timeline for ${playbookRuns[1].name}`);
|
||||
});
|
||||
|
||||
it('update', () => {
|
||||
// # Run a slash command with not enough parameters
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Command expects one argument: the run number.');
|
||||
|
||||
// # Run a slash command wrong run number
|
||||
cy.uiPostMessageQuickly('/playbook update 2');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Invalid run number');
|
||||
|
||||
// # Type a command
|
||||
cy.findByTestId('post_textbox').clear().type('/playbook update ');
|
||||
|
||||
// * Verify suggestions number: 2 runs + 1 title
|
||||
cy.get('.slash-command').should('have.length', 3);
|
||||
|
||||
// # Clear input
|
||||
cy.findByTestId('post_textbox').clear();
|
||||
|
||||
// # Run a slash command with correct parameters
|
||||
cy.uiPostMessageQuickly('/playbook update 1');
|
||||
|
||||
// # Get dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// # Enter valid data
|
||||
cy.findByTestId('update_run_status_textbox').type('valid update');
|
||||
|
||||
// # Submit the dialog.
|
||||
cy.get('button.confirm').click();
|
||||
});
|
||||
|
||||
// * Verify that the Post update dialog has gone.
|
||||
cy.getStatusUpdateDialog().should('not.exist');
|
||||
|
||||
// * Verify that the status update was posted.
|
||||
cy.getLastPost().within(() => {
|
||||
cy.findByText('posted an update for').should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// 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 > slash command > info', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
let testPlaybook;
|
||||
let testPlaybookRun;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiCreateUser().then(({user: user2}) => {
|
||||
testUser2 = user2;
|
||||
cy.apiAddUserToTeam(testTeam.id, testUser2.id);
|
||||
});
|
||||
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook',
|
||||
checklists: [
|
||||
{
|
||||
title: 'Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
],
|
||||
memberIDs: [testUser.id],
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName: 'Playbook Run',
|
||||
ownerUserId: testUser.id,
|
||||
}).then((playbookRun) => {
|
||||
testPlaybookRun = playbookRun;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Reset the owner back to testUser as necessary.
|
||||
cy.apiChangePlaybookRunOwner(testPlaybookRun.id, testUser.id);
|
||||
});
|
||||
|
||||
describe('/playbook info', () => {
|
||||
it('should show an error when not in a playbook run channel', () => {
|
||||
// # Navigate to a non-playbook run channel.
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Run a slash command to show the playbook run's info.
|
||||
cy.uiPostMessageQuickly('/playbook info');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('This command only works when run from a playbook run channel.');
|
||||
});
|
||||
|
||||
it('should open the RHS when it is not open', () => {
|
||||
// # Navigate directly to the application and the playbook run channel.
|
||||
cy.visit(`/${testTeam.name}/channels/playbook-run`);
|
||||
|
||||
// # Close the RHS, which is opened by default when navigating to a playbook run channel.
|
||||
cy.get('#searchResultsCloseButton').click();
|
||||
|
||||
// * Verify that the RHS is indeed closed.
|
||||
cy.get('#rhsContainer').should('not.exist');
|
||||
|
||||
// # Run a slash command to show the playbook run's info.
|
||||
cy.uiPostMessageQuickly('/playbook info');
|
||||
|
||||
// * Verify that the RHS is now open.
|
||||
cy.get('#rhsContainer').should('be.visible');
|
||||
});
|
||||
|
||||
it('should show an ephemeral post when the RHS is already open', () => {
|
||||
// # Navigate directly to the application and the playbook run channel.
|
||||
cy.visit(`/${testTeam.name}/channels/playbook-run`);
|
||||
|
||||
// * Verify that the RHS is open.
|
||||
cy.get('#rhsContainer').should('be.visible');
|
||||
|
||||
// # Run a slash command to show the playbook run's info.
|
||||
cy.uiPostMessageQuickly('/playbook info');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Your playbook run details are already open in the right hand side of the channel.');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,222 @@
|
||||
// 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 > slash command > owner', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
let testPlaybook;
|
||||
let testPlaybookRun;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiCreateUser().then(({user: user2}) => {
|
||||
testUser2 = user2;
|
||||
cy.apiAddUserToTeam(testTeam.id, testUser2.id);
|
||||
});
|
||||
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook',
|
||||
checklists: [
|
||||
{
|
||||
title: 'Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
],
|
||||
memberIDs: [testUser.id],
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName: 'Playbook Run',
|
||||
ownerUserId: testUser.id,
|
||||
}).then((playbookRun) => {
|
||||
testPlaybookRun = playbookRun;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Reset the owner back to testUser as necessary.
|
||||
cy.apiChangePlaybookRunOwner(testPlaybookRun.id, testUser.id);
|
||||
});
|
||||
|
||||
describe('/playbook owner', () => {
|
||||
it('should show an error when not in a playbook run channel', () => {
|
||||
// # Navigate to a non-playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Run a slash command to show the current owner
|
||||
cy.uiPostMessageQuickly('/playbook owner');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('This command only works when run from a playbook run channel.');
|
||||
});
|
||||
|
||||
it('should show the current owner', () => {
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/playbook-run`);
|
||||
|
||||
// # Run a slash command to show the current owner
|
||||
cy.uiPostMessageQuickly('/playbook owner');
|
||||
|
||||
// * Verify the expected owner.
|
||||
cy.verifyEphemeralMessage(`@${testUser.username} is the current owner for this playbook run.`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('/playbook owner @username', () => {
|
||||
it('should show an error when not in a playbook run channel', () => {
|
||||
// # Navigate to a non-playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Run a slash command to change the current owner
|
||||
cy.uiPostMessageQuickly(`/playbook owner ${testUser2.username}`);
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('This command only works when run from a playbook run channel.');
|
||||
});
|
||||
|
||||
describe('should show an error when the user is not found', () => {
|
||||
beforeEach(() => {
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/playbook-run`);
|
||||
});
|
||||
|
||||
it('when the username has no @-prefix', () => {
|
||||
// # Run a slash command to change the current owner
|
||||
cy.uiPostMessageQuickly('/playbook owner unknown');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Unable to find user @unknown');
|
||||
});
|
||||
|
||||
it('when the username has an @-prefix', () => {
|
||||
// # Run a slash command to change the current owner
|
||||
cy.uiPostMessageQuickly('/playbook owner @unknown');
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Unable to find user @unknown');
|
||||
});
|
||||
});
|
||||
|
||||
describe('should not show an error when the user is not in the channel', () => {
|
||||
beforeEach(() => {
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/playbook-run`);
|
||||
|
||||
// # Ensure the user3 is not part of the channel.
|
||||
cy.uiPostMessageQuickly(`/kick ${testUser2.username}`);
|
||||
});
|
||||
|
||||
it('when the username has no @-prefix', () => {
|
||||
// # Run a slash command to change the current owner
|
||||
cy.uiPostMessageQuickly(`/playbook owner ${testUser2.username}`);
|
||||
|
||||
// * Verify the owner has changed.
|
||||
cy.findByTestId('owner-profile-selector').contains(testUser2.username);
|
||||
});
|
||||
|
||||
it('when the username has an @-prefix', () => {
|
||||
// # Run a slash command to change the current owner
|
||||
cy.uiPostMessageQuickly(`/playbook owner @${testUser2.username}`);
|
||||
|
||||
// * Verify the owner has changed.
|
||||
cy.findByTestId('owner-profile-selector').contains(testUser2.username);
|
||||
});
|
||||
});
|
||||
|
||||
describe('should show a message when the user is already the owner', () => {
|
||||
beforeEach(() => {
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/playbook-run`);
|
||||
});
|
||||
|
||||
it('when the username has no @-prefix', () => {
|
||||
// # Run a slash command to change the current owner
|
||||
cy.uiPostMessageQuickly(`/playbook owner ${testUser.username}`);
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage(`User @${testUser.username} is already owner of this playbook run.`);
|
||||
});
|
||||
|
||||
it('when the username has an @-prefix', () => {
|
||||
// # Run a slash command to change the current owner
|
||||
cy.uiPostMessageQuickly(`/playbook owner @${testUser.username}`);
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage(`User @${testUser.username} is already owner of this playbook run.`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('should change the current owner', () => {
|
||||
beforeEach(() => {
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/playbook-run`);
|
||||
|
||||
// # Ensure the testUser2 is part of the channel.
|
||||
cy.uiPostMessageQuickly(`/invite ${testUser2.username}`);
|
||||
});
|
||||
|
||||
it('when the username has no @-prefix', () => {
|
||||
// # Run a slash command to change the current owner
|
||||
cy.uiPostMessageQuickly(`/playbook owner ${testUser2.username}`);
|
||||
|
||||
// # Verify the owner has changed.
|
||||
cy.findByTestId('owner-profile-selector').contains(testUser2.username);
|
||||
});
|
||||
|
||||
it('when the username has an @-prefix', () => {
|
||||
// # Run a slash command to change the current owner
|
||||
cy.uiPostMessageQuickly(`/playbook owner @${testUser2.username}`);
|
||||
|
||||
// # Verify the owner has changed.
|
||||
cy.findByTestId('owner-profile-selector').contains(testUser2.username);
|
||||
});
|
||||
});
|
||||
|
||||
it('should show an error when specifying more than one username', () => {
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/playbook-run`);
|
||||
|
||||
// # Run a slash command with too many parameters
|
||||
cy.uiPostMessageQuickly(`/playbook owner ${testUser.username} ${testUser2.username}`);
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('/playbook owner expects at most one argument.');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,255 @@
|
||||
// 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 > slash command > test', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
let testPlaybook;
|
||||
let testPlaybookRun;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiCreateUser().then(({user: user2}) => {
|
||||
testUser2 = user2;
|
||||
cy.apiAddUserToTeam(testTeam.id, testUser2.id);
|
||||
});
|
||||
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook',
|
||||
checklists: [
|
||||
{
|
||||
title: 'Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
],
|
||||
memberIDs: [testUser.id],
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName: 'Playbook Run',
|
||||
ownerUserId: testUser.id,
|
||||
}).then((playbookRun) => {
|
||||
testPlaybookRun = playbookRun;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Reset the owner back to testUser as necessary.
|
||||
cy.apiChangePlaybookRunOwner(testPlaybookRun.id, testUser.id);
|
||||
});
|
||||
|
||||
describe('as a regular user', () => {
|
||||
before(() => {
|
||||
// # Login as sysadmin.
|
||||
cy.apiAdminLogin();
|
||||
|
||||
// # Set EnableTesting to true.
|
||||
cy.apiUpdateConfig({
|
||||
ServiceSettings: {
|
||||
EnableTesting: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as user-1
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Navigate to a channel.
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
});
|
||||
|
||||
it('fails to run subcommand bulk-data', () => {
|
||||
// # Execute the bulk-data command.
|
||||
cy.uiPostMessageQuickly('/playbook test bulk-data');
|
||||
|
||||
// * Verify the ephemeral message warns that the user is not admin.
|
||||
cy.verifyEphemeralMessage('Running the test command is restricted to system administrators.');
|
||||
});
|
||||
|
||||
it('fails to run subcommand create-playbook-run', () => {
|
||||
// # Execute the create-playbook-run command.
|
||||
cy.uiPostMessageQuickly('/playbook test create-playbook-run');
|
||||
|
||||
// * Verify the ephemeral message warns that the user is not admin.
|
||||
cy.verifyEphemeralMessage('Running the test command is restricted to system administrators.');
|
||||
});
|
||||
|
||||
it('fails to run subcommand self', () => {
|
||||
// # Execute the self command.
|
||||
cy.uiPostMessageQuickly('/playbook test self');
|
||||
|
||||
// * Verify the ephemeral message warns that the user is not admin.
|
||||
cy.verifyEphemeralMessage('Running the test command is restricted to system administrators.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('as an admin', () => {
|
||||
describe('with EnableTesting set to false', () => {
|
||||
before(() => {
|
||||
// # Login as sysadmin.
|
||||
cy.apiAdminLogin();
|
||||
|
||||
// # Set EnableTesting to false.
|
||||
cy.apiUpdateConfig({
|
||||
ServiceSettings: {
|
||||
EnableTesting: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as sysadmin.
|
||||
cy.apiAdminLogin();
|
||||
|
||||
// # Navigate to a channel.
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
});
|
||||
|
||||
it('fails to run subcommand bulk-data', () => {
|
||||
// # Execute the bulk-data command.
|
||||
cy.uiPostMessageQuickly('/playbook test bulk-data');
|
||||
|
||||
// * Verify the ephemeral message warns that the user is not admin.
|
||||
cy.verifyEphemeralMessage('Setting EnableTesting must be set to true to run the test command.');
|
||||
});
|
||||
|
||||
it('fails to run subcommand create-playbook-run', () => {
|
||||
// # Execute the create-playbook-run command.
|
||||
cy.uiPostMessageQuickly('/playbook test create-playbook-run');
|
||||
|
||||
// * Verify the ephemeral message warns that the user is not admin.
|
||||
cy.verifyEphemeralMessage('Setting EnableTesting must be set to true to run the test command.');
|
||||
});
|
||||
|
||||
it('fails to run subcommand self', () => {
|
||||
// # Execute the self command.
|
||||
cy.uiPostMessageQuickly('/playbook test self');
|
||||
|
||||
// * Verify the ephemeral message warns that the user is not admin.
|
||||
cy.verifyEphemeralMessage('Setting EnableTesting must be set to true to run the test command.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with EnableTesting set to true', () => {
|
||||
before(() => {
|
||||
// # Login as sysadmin.
|
||||
cy.apiAdminLogin();
|
||||
|
||||
// # Set EnableTesting to true.
|
||||
cy.apiUpdateConfig({
|
||||
ServiceSettings: {
|
||||
EnableTesting: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as sysadmin.
|
||||
cy.apiAdminLogin();
|
||||
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Navigate to a channel.
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
});
|
||||
|
||||
describe('with subcommand self', () => {
|
||||
it('asks for confirmation', () => {
|
||||
// # Execute the self command.
|
||||
cy.uiPostMessageQuickly('/playbook test self');
|
||||
|
||||
// * Verify the ephemeral message asks for the confirmation keywords.
|
||||
cy.verifyEphemeralMessage('Are you sure you want to self-test (which will nuke the database and delete all data -- instances, configuration)? All data will be lost. To self-test, type /playbook test self CONFIRM TEST SELF');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with subcommand create', () => {
|
||||
it('fails to run with no arguments', () => {
|
||||
// # Execute the create-playbook-run command with no arguments.
|
||||
cy.uiPostMessageQuickly('/playbook test create-playbook-run');
|
||||
|
||||
// * Verify the ephemeral message warns about the parameters.
|
||||
cy.verifyEphemeralMessage('The command expects three parameters: <playbook_id> <timestamp> <name>');
|
||||
});
|
||||
|
||||
it('fails to run with one argument', () => {
|
||||
// # Execute the create-playbook-run command with one argument.
|
||||
cy.uiPostMessageQuickly(`/playbook test create-playbook-run ${testPlaybook.id}`);
|
||||
|
||||
// * Verify the ephemeral message warns about the parameters.
|
||||
cy.verifyEphemeralMessage('The command expects three parameters: <playbook_id> <timestamp> <name>');
|
||||
});
|
||||
|
||||
it('fails to run with two arguments', () => {
|
||||
// # Execute the create-playbook-run command with two arguments.
|
||||
cy.uiPostMessageQuickly(`/playbook test create-playbook-run ${testPlaybook.id} 2020-01-01`);
|
||||
|
||||
// * Verify the ephemeral message warns about the parameters.
|
||||
cy.verifyEphemeralMessage('The command expects three parameters: <playbook_id> <timestamp> <name>');
|
||||
});
|
||||
|
||||
it('fails to run with a malformed playbook ID', () => {
|
||||
// # Execute the create-playbook-run command with all arguments, but a malformed plabook ID.
|
||||
cy.uiPostMessageQuickly('/playbook test create-playbook-run unknownID 2020-01-01 The playbook run name');
|
||||
|
||||
// * Verify the ephemeral message warns about the ID.
|
||||
cy.verifyEphemeralMessage('The first parameter, <playbook_id>, must be a valid ID.');
|
||||
});
|
||||
|
||||
it('fails to run with a valid, but unknown playbook ID', () => {
|
||||
// # Execute the create-playbook-run command with all arguments, but an unknown plabook ID.
|
||||
cy.uiPostMessageQuickly('/playbook test create-playbook-run abcdefghijklmnopqrstuvwxyz 2020-01-01 The playbook run name');
|
||||
|
||||
// * Verify the ephemeral message warns about the parameter.
|
||||
cy.verifyEphemeralMessage('The playbook with ID \'abcdefghijklmnopqrstuvwxyz\' does not exist.');
|
||||
});
|
||||
|
||||
it('fails to run with a malformed date', () => {
|
||||
// # Execute the create-playbook-run command with all arguments, but a malformed creation timestamp.
|
||||
cy.uiPostMessageQuickly(`/playbook test create-playbook-run ${testPlaybook.id} 2020-1-1 The playbook run name`);
|
||||
|
||||
// * Verify the ephemeral message warns about the parameter.
|
||||
cy.verifyEphemeralMessage('Timestamp \'2020-1-1\' could not be parsed as a date. If you want the playbook run to start on January 2, 2006, the timestamp should be \'2006-01-02\'.');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,322 @@
|
||||
// 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 > slash command > todo', () => {
|
||||
let team1;
|
||||
let team2;
|
||||
let testUser;
|
||||
let testOtherUser;
|
||||
let run1;
|
||||
let run2;
|
||||
let run3;
|
||||
let run4;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
team1 = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiCreateUser().then(({user: otherUser}) => {
|
||||
testOtherUser = otherUser;
|
||||
|
||||
// # Add this new user to the team
|
||||
cy.apiAddUserToTeam(team1.id, testOtherUser.id);
|
||||
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a public playbook
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: team1.id,
|
||||
title: 'Playbook One',
|
||||
memberIDs: [],
|
||||
createPublicPlaybookRun: true,
|
||||
checklists: [
|
||||
{
|
||||
title: 'Playbook One - Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Playbook One - Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
],
|
||||
}).then(({id: playbookId}) => {
|
||||
// # Create two runs in team 1.
|
||||
const now = Date.now();
|
||||
cy.apiRunPlaybook({
|
||||
teamId: team1.id,
|
||||
playbookId,
|
||||
playbookRunName: 'Playbook Run (' + now + ')',
|
||||
ownerUserId: testUser.id,
|
||||
}).then((run) => {
|
||||
run1 = run;
|
||||
});
|
||||
|
||||
const now2 = Date.now() + 100;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: team1.id,
|
||||
playbookId,
|
||||
playbookRunName: 'Playbook Run (' + now2 + ')',
|
||||
ownerUserId: testUser.id,
|
||||
}).then((run) => {
|
||||
run2 = run;
|
||||
});
|
||||
});
|
||||
|
||||
// # Create a second team to test cross-team notifications
|
||||
cy.apiCreateTeam('team2', 'Team 2').then(({team: secondTeam}) => {
|
||||
team2 = secondTeam;
|
||||
|
||||
cy.apiAdminLogin();
|
||||
cy.apiAddUserToTeam(team2.id, testUser.id);
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a public playbook
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: team2.id,
|
||||
title: 'Playbook Two',
|
||||
memberIDs: [],
|
||||
createPublicPlaybookRun: true,
|
||||
checklists: [
|
||||
{
|
||||
title: 'Playbook Two - Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Playbook Two - Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
],
|
||||
}).then(({id: playbookId}) => {
|
||||
// # Create one run in team 2.
|
||||
const now = Date.now() + 200;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: team2.id,
|
||||
playbookId,
|
||||
playbookRunName: 'Playbook Run (' + now + ')',
|
||||
ownerUserId: testUser.id,
|
||||
}).then((run) => {
|
||||
run3 = run;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// # Create another playbook with runs owned by another user
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: team1.id,
|
||||
title: 'Playbook Other',
|
||||
memberIDs: [],
|
||||
createPublicPlaybookRun: true,
|
||||
checklists: [
|
||||
{
|
||||
title: 'Playbook Other - Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Playbook Other - Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1'},
|
||||
{title: 'Step 2'},
|
||||
],
|
||||
},
|
||||
],
|
||||
}).then(({id: playbookId}) => {
|
||||
// # Login as testOtherUser
|
||||
cy.apiLogin(testOtherUser);
|
||||
|
||||
// # Create a run in team 1, with testOtherUser as owner and inviting testUser
|
||||
const now = Date.now();
|
||||
cy.apiRunPlaybook({
|
||||
teamId: team1.id,
|
||||
playbookId,
|
||||
playbookRunName: 'Other Playbook Run (' + now + ')',
|
||||
ownerUserId: testOtherUser.id,
|
||||
}).then((run) => {
|
||||
run4 = run;
|
||||
|
||||
// # Invite testUser to the channel
|
||||
// cy.apiAddUserToChannel(run.channel_id, testUser.id);
|
||||
cy.apiAddUsersToRun(run.id, [testUser.id]);
|
||||
|
||||
// # Force this run to be overdue
|
||||
cy.apiUpdateStatus({
|
||||
playbookRunId: run4.id,
|
||||
message: 'no message 4',
|
||||
reminder: 1,
|
||||
});
|
||||
});
|
||||
|
||||
// # Create a run in team 1, with testOtherUser as owner but not inviting testUser
|
||||
const now2 = Date.now() + 100;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: team1.id,
|
||||
playbookId,
|
||||
playbookRunName: 'Other Playbook Run (' + now2 + ')',
|
||||
ownerUserId: testOtherUser.id,
|
||||
}).then((run) => {
|
||||
// # Force this run to be overdue
|
||||
cy.apiUpdateStatus({
|
||||
playbookRunId: run.id,
|
||||
message: 'no message 5',
|
||||
reminder: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
});
|
||||
|
||||
describe('/playbook todo should show', () => {
|
||||
it('three runs', () => {
|
||||
// # Navigate to a non-playbook run channel.
|
||||
cy.visit(`/${team2.name}/channels/town-square`);
|
||||
|
||||
// # Run a slash command to show the to-do list.
|
||||
cy.uiPostMessageQuickly('/playbook todo');
|
||||
|
||||
cy.getLastPost().within((post) => {
|
||||
// * Should show titles
|
||||
cy.wrap(post).contains('You have 0 runs overdue.');
|
||||
cy.wrap(post).contains('You have 0 assigned tasks.');
|
||||
cy.wrap(post).contains('You have 4 runs currently in progress:');
|
||||
|
||||
// * Should show four active runs
|
||||
cy.get('li').then((liItems) => {
|
||||
expect(liItems[0]).to.contain.text(run4.name);
|
||||
expect(liItems[1]).to.contain.text(run1.name);
|
||||
expect(liItems[2]).to.contain.text(run2.name);
|
||||
expect(liItems[3]).to.contain.text(run3.name);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('four assigned tasks', () => {
|
||||
// # assign self four tasks
|
||||
cy.apiChangeChecklistItemAssignee(run1.id, 0, 0, testUser.id);
|
||||
cy.apiChangeChecklistItemAssignee(run1.id, 1, 1, testUser.id);
|
||||
cy.apiChangeChecklistItemAssignee(run2.id, 0, 1, testUser.id);
|
||||
cy.apiChangeChecklistItemAssignee(run3.id, 1, 0, testUser.id);
|
||||
|
||||
// # Navigate to a non-playbook run channel.
|
||||
cy.visit(`/${team2.name}/channels/town-square`);
|
||||
|
||||
// # Run a slash command to show the to-do list.
|
||||
cy.uiPostMessageQuickly('/playbook todo');
|
||||
|
||||
cy.getLastPost().within((post) => {
|
||||
// * Should show titles
|
||||
cy.wrap(post).contains('You have 0 runs overdue.');
|
||||
cy.wrap(post).contains('You have 4 total assigned tasks:');
|
||||
|
||||
// * Should show 3 runs w/ tasks
|
||||
cy.get('.post__body a').then((links) => {
|
||||
expect(links[0]).to.contain.text(run1.name);
|
||||
expect(links[1]).to.contain.text(run2.name);
|
||||
expect(links[2]).to.contain.text(run3.name);
|
||||
});
|
||||
|
||||
cy.get('.post__body li').then((items) => {
|
||||
// * first run
|
||||
expect(items[0]).to.contain.text('Playbook One - Stage 1: Step 1');
|
||||
expect(items[1]).to.contain.text('Playbook One - Stage 2: Step 2');
|
||||
|
||||
// * second run
|
||||
expect(items[2]).to.contain.text('Playbook One - Stage 1: Step 2');
|
||||
|
||||
// * third run
|
||||
expect(items[3]).to.contain.text('Playbook Two - Stage 2: Step 1');
|
||||
});
|
||||
});
|
||||
|
||||
// # check two of the items via API
|
||||
cy.apiSetChecklistItemState(run1.id, 0, 0, 'closed');
|
||||
cy.apiSetChecklistItemState(run3.id, 1, 0, 'closed');
|
||||
|
||||
// # Show the to-do list.
|
||||
cy.uiPostMessageQuickly('/playbook todo');
|
||||
|
||||
// * Should show 2 tasks
|
||||
cy.getLastPost().within((post) => {
|
||||
// * Should show titles
|
||||
cy.wrap(post).contains('You have 0 runs overdue.');
|
||||
cy.wrap(post).contains('You have 2 total assigned tasks:');
|
||||
|
||||
// * Should show 2 runs w/ tasks
|
||||
cy.get('.post__body a').then((links) => {
|
||||
expect(links[0]).to.contain.text(run1.name);
|
||||
expect(links[1]).to.contain.text(run2.name);
|
||||
});
|
||||
|
||||
cy.get('.post__body li').then((items) => {
|
||||
// * first run
|
||||
expect(items[0]).to.contain.text('Playbook One - Stage 2: Step 2');
|
||||
|
||||
// * second run
|
||||
expect(items[1]).to.contain.text('Playbook One - Stage 1: Step 2');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('two overdue status updates', () => {
|
||||
// # set two updates with short timers
|
||||
cy.apiUpdateStatus({
|
||||
playbookRunId: run1.id,
|
||||
message: 'no message 1',
|
||||
reminder: 1,
|
||||
});
|
||||
cy.apiUpdateStatus({
|
||||
playbookRunId: run3.id,
|
||||
message: 'no message 3',
|
||||
reminder: 1,
|
||||
});
|
||||
|
||||
cy.wait(1100);
|
||||
|
||||
// # Switch to playbooks DM channel
|
||||
cy.visit(`/${team2.name}/messages/@playbooks`);
|
||||
|
||||
// # Run a slash command to show the to-do list.
|
||||
cy.uiPostMessageQuickly('/playbook todo');
|
||||
|
||||
// # Should show two runs overdue -- ignoring the rest
|
||||
cy.getLastPost().within(() => {
|
||||
cy.get('.post__body li').then((liItems) => {
|
||||
expect(liItems[0]).to.contain.text(run1.name);
|
||||
expect(liItems[1]).to.contain.text(run3.name);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Ссылка в новой задаче
Block a user