Move /e2e -> /e2e-tests
Этот коммит содержится в:
@@ -0,0 +1,132 @@
|
||||
// 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 > rhs > header', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
let testPlaybookRun;
|
||||
let playbookRunChannelName;
|
||||
let playbookRunName;
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a playbook
|
||||
cy.apiCreateTestPlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook',
|
||||
userId: testUser.id,
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Run the 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,
|
||||
}).then((run) => {
|
||||
testPlaybookRun = run;
|
||||
});
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
});
|
||||
|
||||
describe('shows name', () => {
|
||||
it('of active playbook run', () => {
|
||||
// * Verify the title is displayed
|
||||
cy.get('#rhsContainer').contains(playbookRunName);
|
||||
});
|
||||
|
||||
it('of renamed playbook run', () => {
|
||||
// * Verify the existing title is displayed
|
||||
cy.get('#rhsContainer').contains(playbookRunName);
|
||||
|
||||
// # Rename the channel
|
||||
cy.apiPatchChannel(testPlaybookRun.channel_id, {
|
||||
id: testPlaybookRun.channel_id,
|
||||
display_name: 'Updated',
|
||||
});
|
||||
|
||||
// * Verify the updated title is displayed
|
||||
cy.get('#rhsContainer').contains(playbookRunName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('edit run name', () => {
|
||||
it('by clicking on name', () => {
|
||||
cy.get('#rhsContainer').findByTestId('rendered-run-name').should('be.visible').click();
|
||||
|
||||
// # type text in textarea
|
||||
cy.get('#rhsContainer').findByTestId('textarea-run-name').should('be.visible').clear().type('new run name{ctrl+enter}');
|
||||
|
||||
// * make sure the updated name is here
|
||||
cy.get('#rhsContainer').findByTestId('rendered-run-name').should('be.visible').contains('new run name');
|
||||
|
||||
// * make sure the channel name remains unchanged
|
||||
cy.get('#channelHeaderInfo').findByRole('heading').contains(playbookRunName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('edit summary', () => {
|
||||
it('by clicking on placeholder', () => {
|
||||
cy.get('#rhsContainer').findByTestId('rendered-description').should('be.visible').click();
|
||||
|
||||
// # type text in textarea
|
||||
cy.get('#rhsContainer').findByTestId('textarea-description').should('be.visible').type('new summary{ctrl+enter}');
|
||||
|
||||
// * make sure the updated summary is here
|
||||
cy.get('#rhsContainer').findByTestId('rendered-description').should('be.visible').contains('new summary');
|
||||
});
|
||||
|
||||
it('by clicking on dot menu item', () => {
|
||||
// # click on the field
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
cy.findByTestId('buttons-row').invoke('show').within(() => {
|
||||
cy.findAllByRole('button').eq(1).click();
|
||||
});
|
||||
});
|
||||
|
||||
cy.findByText('Edit run summary').click({force: true});
|
||||
|
||||
// # type text in textarea
|
||||
cy.focused().should('be.visible').type('new summary{ctrl+enter}');
|
||||
|
||||
// * make sure the updated summary is here
|
||||
cy.get('#rhsContainer').findByTestId('rendered-description').should('be.visible').contains('new summary');
|
||||
});
|
||||
});
|
||||
|
||||
describe('participate', () => {
|
||||
it('icon is not visible if I am a participant', () => {
|
||||
// * assert icon is not visible if I'm participant
|
||||
cy.get('#rhsContainer').findByTestId('rhs-participate-icon').should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,489 @@
|
||||
// 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 {HALF_SEC, ONE_SEC} from '../../../../fixtures/timeouts';
|
||||
|
||||
describe('channels > rhs > checklist', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a playbook
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: team.id,
|
||||
title: 'Playbook',
|
||||
checklists: [
|
||||
{
|
||||
title: 'Stage 1',
|
||||
items: [
|
||||
{title: 'Step 1', command: '/invalid'},
|
||||
{title: 'Step 2', command: '/echo VALID'},
|
||||
{title: 'Step 3', command: '/playbook check 0 0'},
|
||||
{title: 'Step 4'},
|
||||
{title: 'Step 5'},
|
||||
{title: 'Step 6'},
|
||||
{title: 'Step 7'},
|
||||
{title: 'Step 8'},
|
||||
{title: 'Step 9'},
|
||||
{title: 'Step 10'},
|
||||
{title: 'Step 11'},
|
||||
{title: 'Step 12'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Stage 2',
|
||||
items: [
|
||||
{title: 'Step 1', command: '/invalid'},
|
||||
{title: 'Step 2', command: '/echo VALID'},
|
||||
{title: 'Step 3'},
|
||||
{title: 'Step 4'},
|
||||
{title: 'Step 5'},
|
||||
{title: 'Step 6'},
|
||||
{title: 'Step 7'},
|
||||
{title: 'Step 8'},
|
||||
{title: 'Step 9'},
|
||||
{title: 'Step 10'},
|
||||
{title: 'Step 11'},
|
||||
{title: 'Step 12'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Stage 3',
|
||||
items: [
|
||||
{title: 'Step 1', command: '/invalid'},
|
||||
{title: 'Step 2', command: '/echo VALID'},
|
||||
{title: 'Step 3'},
|
||||
{title: 'Step 4'},
|
||||
{title: 'Step 5'},
|
||||
{title: 'Step 6'},
|
||||
{title: 'Step 7'},
|
||||
{title: 'Step 8'},
|
||||
{title: 'Step 9'},
|
||||
{title: 'Step 10'},
|
||||
{title: 'Step 11'},
|
||||
{title: 'Step 12'},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Stage 3',
|
||||
items: [
|
||||
{title: 'Step 1', command: '/invalid'},
|
||||
{title: 'Step 2', command: '/echo VALID'},
|
||||
{title: 'Step 3'},
|
||||
{title: 'Step 4'},
|
||||
{title: 'Step 5'},
|
||||
{title: 'Step 6'},
|
||||
{title: 'Step 7'},
|
||||
{title: 'Step 8'},
|
||||
{title: 'Step 9'},
|
||||
{title: 'Step 10'},
|
||||
{title: 'Step 11'},
|
||||
{title: 'Step 12'},
|
||||
],
|
||||
},
|
||||
],
|
||||
memberIDs: [
|
||||
user.id,
|
||||
],
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// // # Switch to clean display mode
|
||||
// cy.apiSaveMessageDisplayPreference('clean');
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Size the viewport to task list without scrolling issues
|
||||
cy.viewport('macbook-13');
|
||||
});
|
||||
|
||||
describe('rhs stuff', () => {
|
||||
let playbookRunName;
|
||||
let playbookRunChannelName;
|
||||
|
||||
beforeEach(() => {
|
||||
// # Run the 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,
|
||||
});
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
|
||||
// * Verify the playbook run RHS is open.
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
cy.findByText(playbookRunName).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('header', () => {
|
||||
it('has title', () => {
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
cy.findByText('Tasks').should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('shows an ephemeral error when running an invalid slash command', () => {
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
// * Verify the command has not yet been run.
|
||||
cy.findAllByTestId('run').eq(0).should('have.text', 'Run');
|
||||
|
||||
// * Run the /invalid slash command
|
||||
cy.findAllByTestId('run').eq(0).click();
|
||||
|
||||
// * Verify the command still has not yet been run.
|
||||
cy.findAllByTestId('run').eq(0).should('have.text', 'Run');
|
||||
});
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Failed to execute slash command /invalid');
|
||||
});
|
||||
|
||||
it('successfully runs a valid slash command', () => {
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
// * Verify the command has not yet been run.
|
||||
cy.findAllByTestId('run').eq(1).should('have.text', 'Run');
|
||||
|
||||
// * Run the /invalid slash command
|
||||
cy.findAllByTestId('run').eq(1).click();
|
||||
|
||||
// * Verify the command has now been run.
|
||||
cy.findAllByTestId('run').eq(1).should('have.text', 'Rerun');
|
||||
});
|
||||
|
||||
// # Verify the expected output.
|
||||
cy.verifyPostedMessage('VALID');
|
||||
});
|
||||
|
||||
it('still shows slash commands as having been run after reload', () => {
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
// * Verify the command has not yet been run.
|
||||
cy.findAllByTestId('run').eq(1).should('have.text', 'Run');
|
||||
|
||||
// * Run the /invalid slash command
|
||||
cy.findAllByTestId('run').eq(1).click();
|
||||
|
||||
// * Verify the command has now been run.
|
||||
cy.findAllByTestId('run').eq(1).should('have.text', 'Rerun');
|
||||
});
|
||||
|
||||
// # Verify the expected output.
|
||||
cy.verifyPostedMessage('VALID');
|
||||
|
||||
// # Reload the page
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
// * Verify the invalid command still has not yet been run.
|
||||
cy.findAllByTestId('run').eq(0).should('have.text', 'Run');
|
||||
|
||||
// * Verify the valid command has been run.
|
||||
cy.findAllByTestId('run').eq(1).should('have.text', 'Rerun');
|
||||
});
|
||||
});
|
||||
|
||||
it('runs /playbook slash commands', () => {
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
// * Verify the `/playbook check 0 0` command has not yet been run.
|
||||
cy.findAllByTestId('run').eq(2).should('have.text', 'Run');
|
||||
|
||||
// * Run the slash command
|
||||
cy.findAllByTestId('run').eq(2).click();
|
||||
|
||||
// * Verify the command has now been run.
|
||||
cy.findAllByTestId('run').eq(2).should('have.text', 'Rerun');
|
||||
|
||||
// * Verify the first checklist item is checked
|
||||
cy.findAllByTestId('checkbox-item-container').eq(0).within(() => {
|
||||
// # Check the overdue task
|
||||
cy.get('input').should('be.checked');
|
||||
});
|
||||
});
|
||||
|
||||
// # Reload the page
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
// * Verify the command has still been run.
|
||||
cy.findAllByTestId('run').eq(2).should('have.text', 'Rerun');
|
||||
|
||||
// * Verify the first checklist item is still checked
|
||||
cy.findAllByTestId('checkbox-item-container').eq(0).within(() => {
|
||||
// # Check the overdue task
|
||||
cy.get('input').should('be.checked');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can skip and restore task', () => {
|
||||
// # Skip task and verify
|
||||
skipTask(0);
|
||||
|
||||
// # Hover over the checklist item
|
||||
cy.findAllByTestId('checkbox-item-container').eq(0).trigger('mouseover');
|
||||
|
||||
// # Click dot menu
|
||||
cy.findAllByTestId('checkbox-item-container').eq(0).within(() => {
|
||||
cy.findByTitle('More').click();
|
||||
});
|
||||
|
||||
// # Click the restore button
|
||||
cy.findByRole('button', {name: 'Restore task'}).click();
|
||||
|
||||
// * Verify the item has been restored
|
||||
cy.findAllByTestId('checkbox-item-container').eq(0).within(() => {
|
||||
cy.get('[data-cy=skipped]').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('add new task', () => {
|
||||
const newTasktext = 'This is my new task' + Date.now();
|
||||
|
||||
cy.addNewTaskFromRHS(newTasktext);
|
||||
|
||||
// Check that it was created
|
||||
cy.findByText(newTasktext).should('exist');
|
||||
});
|
||||
|
||||
it('add new task slash command', () => {
|
||||
const newTasktext = 'Task from slash command' + Date.now();
|
||||
|
||||
cy.uiPostMessageQuickly(`/playbook checkadd 0 ${newTasktext}`);
|
||||
|
||||
// Check that it was created
|
||||
cy.findByText(newTasktext).should('exist');
|
||||
});
|
||||
|
||||
it('creates a new checklist', () => {
|
||||
// # Click on the button to add a checklist
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
cy.findByTestId('add-a-checklist-button').click();
|
||||
});
|
||||
|
||||
// # Type a title and click on the Add button
|
||||
const title = 'Checklist - ' + Date.now();
|
||||
cy.findByTestId('checklist-title-input').type(title);
|
||||
cy.findByTestId('checklist-item-save-button').click();
|
||||
|
||||
// # Click on the button to add a checklist
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
cy.findByText(title).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('renames a checklist', () => {
|
||||
const oldTitle = 'Stage 1';
|
||||
const newTitle = 'New title - ' + Date.now();
|
||||
|
||||
// # Open the dot menu and click on the rename button
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
cy.findByText(oldTitle).trigger('mouseover');
|
||||
cy.findAllByTestId('checklistHeader').eq(0).within(() => {
|
||||
cy.findByTitle('More').click();
|
||||
});
|
||||
});
|
||||
cy.findByTestId('dropdownmenu').findByText('Rename checklist').click();
|
||||
|
||||
// # Type the new title and click the confirm button
|
||||
cy.findByTestId('checklist-title-input').type(newTitle);
|
||||
cy.findByTestId('checklist-item-save-button').click();
|
||||
|
||||
// * Verify that the checklist changed its name
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
cy.findByText(oldTitle).should('not.exist');
|
||||
cy.findByText(oldTitle + newTitle).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('can set due date, from hover menu', () => {
|
||||
// # Set due date and verify
|
||||
setTaskDueDate(6, 'in 10 minutes');
|
||||
});
|
||||
|
||||
it('can set due date, from edit mode', () => {
|
||||
// # Hover over the checklist item
|
||||
cy.findAllByTestId('checkbox-item-container').eq(6).trigger('mouseover');
|
||||
|
||||
// # Click the edit button
|
||||
cy.findAllByTestId('hover-menu-edit-button').eq(0).click();
|
||||
|
||||
cy.findAllByTestId('due-date-info-button').eq(0).click();
|
||||
|
||||
// # Enter due date in 3 days
|
||||
cy.get('.playbook-react-select__value-container').type('in 3 days').
|
||||
wait(HALF_SEC).
|
||||
trigger('keydown', {
|
||||
key: 'Enter',
|
||||
});
|
||||
|
||||
// * Verify if Due in 3 days info is added
|
||||
cy.findAllByTestId('due-date-info-button').eq(0).should('exist').within(() => {
|
||||
cy.findByText('in 3 days').should('exist');
|
||||
cy.findByText('Due').should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('filter overdue tasks', {retries: {runMode: 3}}, () => {
|
||||
// # Set overdue date for several items
|
||||
setTaskDueDate(2, '1 hour ago');
|
||||
|
||||
setTaskDueDate(3, '7 hours ago', 1);
|
||||
setTaskDueDate(5, '3 hours ago', 2);
|
||||
setTaskDueDate(6, '6 hours ago', 3);
|
||||
|
||||
// # Skip task
|
||||
skipTask(3);
|
||||
|
||||
// # Mark a task as completed
|
||||
cy.findAllByTestId('checkbox-item-container').eq(5).within(() => {
|
||||
// # Check the overdue task
|
||||
cy.get('input').click();
|
||||
});
|
||||
|
||||
// * Verify if overdue tasks info was added. Should not include skipped / completed tasks.
|
||||
cy.findAllByTestId('overdue-tasks-filter').eq(0).should('exist').within(() => {
|
||||
cy.findByText('2 tasks overdue').should('exist');
|
||||
});
|
||||
|
||||
// # Filter overdue tasks
|
||||
cy.findAllByTestId('overdue-tasks-filter').eq(0).click();
|
||||
|
||||
// * Verify if filter works. Should not include skipped / completed tasks.
|
||||
cy.findAllByTestId('checkbox-item-container').should('have.length', 2);
|
||||
|
||||
// # Cancel filter overdue tasks
|
||||
cy.findAllByTestId('overdue-tasks-filter').eq(0).click();
|
||||
|
||||
// * Verify if filter was canceled
|
||||
cy.findAllByTestId('checkbox-item-container').should('have.length', 48);
|
||||
});
|
||||
|
||||
it('filter overdue automatically disappear if we check all overdue items', () => {
|
||||
// # Set due date
|
||||
setTaskDueDate(2, '1 minute ago');
|
||||
|
||||
// * Verify if overdue tasks info was added
|
||||
cy.findAllByTestId('overdue-tasks-filter').eq(0).should('exist').within(() => {
|
||||
cy.findByText('1 task overdue').should('exist');
|
||||
});
|
||||
|
||||
// # Filter overdue tasks
|
||||
cy.findAllByTestId('overdue-tasks-filter').eq(0).click();
|
||||
|
||||
// * Verify if filter works
|
||||
cy.findAllByTestId('checkbox-item-container').should('have.length', 1);
|
||||
|
||||
// # Mark a task as completed
|
||||
cy.findAllByTestId('checkbox-item-container').within(() => {
|
||||
// # Check the overdue task
|
||||
cy.get('input').click();
|
||||
});
|
||||
|
||||
// * Verify there is no filter
|
||||
cy.findAllByTestId('overdue-tasks-filter').should('not.exist');
|
||||
|
||||
// * Verify if filter was canceled
|
||||
cy.findAllByTestId('checkbox-item-container').should('have.length', 48);
|
||||
});
|
||||
|
||||
it('switching between runs with the same checklist', () => {
|
||||
// # Create another run using the same playbook
|
||||
const playbookRunName2 = 'RunWithSameChecklist';
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName: playbookRunName2,
|
||||
ownerUserId: testUser.id,
|
||||
});
|
||||
|
||||
// # Set due date for the first channel's task
|
||||
setTaskDueDate(2, 'in 2 hours');
|
||||
|
||||
// # Switch to the second run channel
|
||||
cy.get('#sidebarItem_runwithsamechecklist').click();
|
||||
|
||||
// * Verify that tasks do not have due dates
|
||||
cy.findAllByTestId('checkbox-item-container').eq(2).within(() => {
|
||||
cy.findAllByTestId('due-date-info-button').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('scroll 2-3 pages and open due date selector- unexpected scroll issue', () => {
|
||||
// # Hover over the checklist item that is ~3 pages down
|
||||
cy.findAllByTestId('checkbox-item-container').eq(26).trigger('mouseover').within(() => {
|
||||
// # Click the set due date button
|
||||
cy.get('.icon-calendar-outline').click();
|
||||
});
|
||||
|
||||
// * Verify if date selector is visible
|
||||
cy.get('.playbook-react-select').should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const setTaskDueDate = (taskIndex, dateQuery, offset = 0) => {
|
||||
// # Hover over the checklist item
|
||||
cy.findAllByTestId('checkbox-item-container').eq(taskIndex).trigger('mouseover').within(() => {
|
||||
// # Click the set due date button
|
||||
cy.get('.icon-calendar-outline').click();
|
||||
});
|
||||
|
||||
// # Wait for react select to finish rendering.
|
||||
cy.wait(ONE_SEC);
|
||||
|
||||
// # Enter due date query
|
||||
cy.get('.playbook-react-select').within(() => {
|
||||
cy.get('input').type(dateQuery, {force: true}).
|
||||
wait(HALF_SEC).
|
||||
trigger('keydown', {
|
||||
key: 'Enter',
|
||||
});
|
||||
});
|
||||
|
||||
// * Verify if Due date info is added
|
||||
cy.findAllByTestId('due-date-info-button').eq(offset).should('exist').within(() => {
|
||||
cy.findByText(dateQuery).should('exist');
|
||||
cy.findByText('Due').should('exist');
|
||||
});
|
||||
};
|
||||
|
||||
const skipTask = (taskIndex) => {
|
||||
// # Hover over the checklist item
|
||||
cy.findAllByTestId('checkbox-item-container').eq(taskIndex).trigger('mouseover');
|
||||
|
||||
// # Click dot menu
|
||||
cy.findAllByTestId('checkbox-item-container').eq(taskIndex).within(() => {
|
||||
cy.findByTitle('More').click();
|
||||
});
|
||||
|
||||
// # Click the skip button
|
||||
cy.findByRole('button', {name: 'Skip task'}).click();
|
||||
};
|
||||
@@ -0,0 +1,225 @@
|
||||
// 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 > rhs > header', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a playbook
|
||||
cy.apiCreateTestPlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook',
|
||||
userId: testUser.id,
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
});
|
||||
|
||||
describe('shows name', () => {
|
||||
it('of active playbook run', () => {
|
||||
// # Run the playbook
|
||||
const now = Date.now();
|
||||
const playbookRunName = 'Playbook Run (' + now + ')';
|
||||
const playbookRunChannelName = 'playbook-run-' + now;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName,
|
||||
ownerUserId: testUser.id,
|
||||
});
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
|
||||
// * Verify the title is displayed
|
||||
cy.get('#rhsContainer').contains(playbookRunName);
|
||||
});
|
||||
|
||||
it('of renamed playbook run', () => {
|
||||
// # Run the playbook
|
||||
const now = Date.now();
|
||||
const playbookRunName = 'Playbook Run (' + now + ')';
|
||||
const playbookRunChannelName = 'playbook-run-' + now;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName,
|
||||
ownerUserId: testUser.id,
|
||||
}).then((playbookRun) => {
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
|
||||
// * Verify the existing title is displayed
|
||||
cy.get('#rhsContainer').contains(playbookRunName);
|
||||
|
||||
// # Rename the channel
|
||||
cy.apiPatchChannel(playbookRun.channel_id, {
|
||||
id: playbookRun.channel_id,
|
||||
display_name: 'Updated',
|
||||
});
|
||||
|
||||
// * Verify the updated title is displayed
|
||||
cy.get('#rhsContainer').contains(playbookRunName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('edit summary', () => {
|
||||
it('by clicking on placeholder', () => {
|
||||
// # Run the playbook
|
||||
const now = Date.now();
|
||||
const playbookRunName = 'Playbook Run (' + now + ')';
|
||||
const playbookRunChannelName = 'playbook-run-' + now;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName,
|
||||
ownerUserId: testUser.id,
|
||||
});
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
|
||||
// # click on the field
|
||||
cy.get('#rhsContainer').findByTestId('rendered-description').should('be.visible').click();
|
||||
|
||||
// # type text in textarea
|
||||
cy.get('#rhsContainer').findByTestId('textarea-description').should('be.visible').type('new summary{ctrl+enter}');
|
||||
|
||||
// * make sure the updated summary is here
|
||||
cy.get('#rhsContainer').findByTestId('rendered-description').should('be.visible').contains('new summary');
|
||||
|
||||
// * reload the page
|
||||
cy.reload();
|
||||
|
||||
// * make sure the updated summary is still there
|
||||
cy.get('#rhsContainer').findByTestId('rendered-description').should('be.visible').contains('new summary');
|
||||
});
|
||||
|
||||
it('by clicking on dot menu item', () => {
|
||||
// # Run the playbook
|
||||
const now = Date.now();
|
||||
const playbookRunName = 'Playbook Run (' + now + ')';
|
||||
const playbookRunChannelName = 'playbook-run-' + now;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName,
|
||||
ownerUserId: testUser.id,
|
||||
});
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
|
||||
// # click on the field
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
cy.findByTestId('buttons-row').invoke('show').within(() => {
|
||||
cy.findAllByRole('button').eq(1).click();
|
||||
});
|
||||
});
|
||||
|
||||
cy.findByTestId('dropdownmenu').within(() => {
|
||||
cy.get('span').should('have.length', 3);
|
||||
cy.findByText('Edit run summary').click();
|
||||
});
|
||||
|
||||
// # type text in textarea
|
||||
cy.focused().should('be.visible').type('new summary{ctrl+enter}');
|
||||
|
||||
// * make sure the updated summary is here
|
||||
cy.get('#rhsContainer').findByTestId('rendered-description').should('be.visible').contains('new summary');
|
||||
});
|
||||
});
|
||||
|
||||
describe('edit summary of finished run', () => {
|
||||
let playbookRunChannelName;
|
||||
let finishedPlaybookRun;
|
||||
|
||||
beforeEach(() => {
|
||||
// # Run the playbook
|
||||
const now = Date.now();
|
||||
const playbookRunName = 'Playbook Run (' + now + ')';
|
||||
playbookRunChannelName = 'playbook-run-' + now;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName,
|
||||
ownerUserId: testUser.id,
|
||||
}).then((playbookRun) => {
|
||||
finishedPlaybookRun = playbookRun;
|
||||
});
|
||||
});
|
||||
|
||||
it('by clicking on placeholder', () => {
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
|
||||
// # Wait for the RHS to open
|
||||
cy.get('#rhsContainer').should('be.visible');
|
||||
|
||||
// # Mark the run as finished
|
||||
cy.apiFinishRun(finishedPlaybookRun.id);
|
||||
|
||||
// # click on the field
|
||||
cy.get('#rhsContainer').findByTestId('rendered-description').should('be.visible').click();
|
||||
|
||||
// * Verify textarea does not appear
|
||||
cy.get('#rhsContainer').findByTestId('textarea-description').should('not.exist');
|
||||
|
||||
// * Verify no prompt to join appears (timeout ensures it fails right away before toast disappears)
|
||||
cy.findByText('Become a participant to interact with this run', {timeout: 500}).should('not.exist');
|
||||
});
|
||||
|
||||
it('by clicking on dot menu item', () => {
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
|
||||
// # Wait for the RHS to open
|
||||
cy.get('#rhsContainer').should('be.visible');
|
||||
|
||||
// # Mark the run as finished
|
||||
cy.apiFinishRun(finishedPlaybookRun.id);
|
||||
|
||||
// # click on the field
|
||||
cy.get('#rhsContainer').within(() => {
|
||||
cy.findByTestId('buttons-row').invoke('show').within(() => {
|
||||
cy.findAllByRole('button').eq(1).click();
|
||||
});
|
||||
});
|
||||
|
||||
// * Verify the menu items
|
||||
cy.findByTestId('dropdownmenu').within(() => {
|
||||
cy.get('span').should('have.length', 2);
|
||||
cy.findByText('Edit run summary').should('not.exist');
|
||||
});
|
||||
|
||||
// * Verify no prompt to join appears (timeout ensures it fails right away before toast disappears)
|
||||
cy.findByText('Become a participant to interact with this run', {timeout: 500}).should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,159 @@
|
||||
// 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 > rhs > home', () => {
|
||||
let testSysadmin;
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiCreateCustomAdmin().then(({sysadmin}) => {
|
||||
testSysadmin = sysadmin;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('default permission settings', () => {
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Navigate to the application, starting in a non-run channel.
|
||||
cy.visit(`/${testTeam.name}/`);
|
||||
|
||||
// * Check time bar in the channel section
|
||||
// * as an indicator of page stability / end of rendering
|
||||
cy.findByText('Today').should('be.visible');
|
||||
});
|
||||
|
||||
describe('telemetry', () => {
|
||||
it('track page view', () => {
|
||||
// # intercepts telemetry
|
||||
cy.interceptTelemetry();
|
||||
|
||||
// # Click the icon
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// * Assert telemetry data
|
||||
cy.expectTelemetryToContain([{name: 'channels_rhs_home', type: 'page'}]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shows available', () => {
|
||||
it('starter templates', () => {
|
||||
// templates are defined in webapp/src/components/templates/template_data.tsx
|
||||
const templates = [
|
||||
{name: 'Blank', checklists: '1 checklist', actions: '1 action'},
|
||||
{name: 'Product Release', checklists: '4 checklists', actions: '3 actions'},
|
||||
{name: 'Incident Resolution', checklists: '4 checklists', actions: '4 actions'},
|
||||
{name: 'Customer Onboarding', checklists: '4 checklists', actions: '3 actions'},
|
||||
{name: 'Employee Onboarding', checklists: '5 checklists', actions: '2 actions'},
|
||||
{name: 'Feature Lifecycle', checklists: '5 checklists', actions: '3 actions'},
|
||||
{name: 'Bug Bash', checklists: '5 checklists', actions: '3 actions'},
|
||||
{name: 'Learn how to use playbooks', checklists: '2 checklists', actions: '2 actions'},
|
||||
];
|
||||
|
||||
// # Click the icon
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// * Verify the templates are shown
|
||||
cy.findByText('Playbook Templates').
|
||||
parent().
|
||||
next().
|
||||
within(() => {
|
||||
cy.findAllByTestId('template-details').each(($templateElement, index) => {
|
||||
cy.wrap($templateElement).within(() => {
|
||||
cy.findByText(templates[index].name).should('exist');
|
||||
cy.findByText(templates[index].checklists).should('exist');
|
||||
cy.findByText(templates[index].actions).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('show zero case if there are playbooks', () => {
|
||||
beforeEach(() => {
|
||||
// # Create a public playbook
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Team Playbook',
|
||||
memberIDs: [],
|
||||
});
|
||||
|
||||
// # Click the icon
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
});
|
||||
|
||||
it('without pre-populated channel name template', () => {
|
||||
// * Verify the templates are not shown
|
||||
cy.findAllByTestId('template-details').should('not.exist');
|
||||
|
||||
// * Verify the zero case is shown
|
||||
cy.get('#sidebar-right').findByText('There are no runs in progress linked to this channel').should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let restrictedTestTeam;
|
||||
let restrictedTestUser;
|
||||
|
||||
describe('user is lacking permissions to create playbooks', () => {
|
||||
before(() => {
|
||||
cy.apiLogin(testSysadmin);
|
||||
|
||||
cy.apiCreateUser().then(({user}) => {
|
||||
restrictedTestUser = user;
|
||||
});
|
||||
|
||||
cy.apiCreateTeam('restricted-team', 'Restricted Team').then(({team}) => {
|
||||
restrictedTestTeam = team;
|
||||
cy.apiAddUserToTeam(restrictedTestTeam.id, restrictedTestUser.id);
|
||||
});
|
||||
|
||||
cy.apiCreateScheme('Restricted Team Scheme', 'team').then(({scheme}) => {
|
||||
cy.apiSetTeamScheme(restrictedTestTeam.id, scheme.id);
|
||||
cy.apiGetRolesByNames([scheme.default_team_user_role]).then(({roles}) => {
|
||||
const role = roles[0];
|
||||
|
||||
// Remove permissions to create playbooks
|
||||
const permissions = role.permissions.filter((perm) => !(/playbook_(private|public)_create/).test(perm));
|
||||
cy.apiPatchRole(role.id, {permissions});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as user with restricted permissions
|
||||
cy.apiLogin(restrictedTestUser);
|
||||
|
||||
// # Navigate to the application, starting in a non-run channel.
|
||||
cy.visit(`/${restrictedTestTeam.name}/`);
|
||||
});
|
||||
|
||||
it('permission notice should be shown and no create button should exist', () => {
|
||||
// # Click the icon
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
cy.get('#sidebar-right').within(() => {
|
||||
// * Verify notice about missing permissions exists
|
||||
cy.findByText('You don\'t have permission to create playbooks in this workspace.').should('be.visible');
|
||||
|
||||
// * Verify create playbook button does not exist
|
||||
cy.findByText('Create playbook').should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,263 @@
|
||||
// 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 > rhs > runlist', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
let testChannel;
|
||||
const numActiveRuns = 10;
|
||||
const numFinishedRuns = 4;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a playbook
|
||||
cy.apiCreateTestPlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'The playbook name',
|
||||
userId: testUser.id,
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
|
||||
// # Create a test channel
|
||||
cy.apiCreateChannel(testTeam.id, 'channel', 'Channel').then(({channel}) => {
|
||||
testChannel = channel;
|
||||
|
||||
// # Run the playbook a few times in the existing channel
|
||||
for (let i = 0; i < numActiveRuns; i++) {
|
||||
const runName = 'playbook-run-' + i;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
ownerUserId: testUser.id,
|
||||
channelId: testChannel.id,
|
||||
playbookRunName: runName,
|
||||
});
|
||||
}
|
||||
|
||||
// # Do it again but finished
|
||||
for (let i = 0; i < numFinishedRuns; i++) {
|
||||
const runName = 'playbook-run-' + i;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
ownerUserId: testUser.id,
|
||||
channelId: testChannel.id,
|
||||
playbookRunName: runName,
|
||||
}).then((run) => {
|
||||
cy.apiFinishRun(run.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/${testChannel.name}`);
|
||||
|
||||
// # Wait the RHS to load
|
||||
cy.findByText('Runs in progress').should('be.visible');
|
||||
});
|
||||
|
||||
it('track page view', () => {
|
||||
// # intercepts telemetry
|
||||
cy.interceptTelemetry();
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
|
||||
|
||||
// * Assert telemetry data
|
||||
cy.expectTelemetryToContain([{name: 'channels_rhs_runlist', type: 'page'}]);
|
||||
});
|
||||
|
||||
it('can filter', () => {
|
||||
// # Click the filter menu
|
||||
cy.findByTestId('rhs-runs-filter-menu').click();
|
||||
|
||||
// * Verify displayed options
|
||||
cy.get('[data-testid="dropdownmenu"] > :nth-child(1) > div').should('have.text', numActiveRuns);
|
||||
cy.get('[data-testid="dropdownmenu"] > :nth-child(2) > div').should('have.text', numFinishedRuns);
|
||||
|
||||
// # Click the filter
|
||||
cy.get('[data-testid="dropdownmenu"] > :nth-child(2)').click();
|
||||
|
||||
// * Verify displayed options
|
||||
cy.get('[data-testid="rhs-runs-list"]').children().should('have.length', numFinishedRuns);
|
||||
});
|
||||
|
||||
it('can show more (pagination)', () => {
|
||||
// * Verify we have the first page
|
||||
cy.get('[data-testid="rhs-runs-list"] > div').should('have.length', 8);
|
||||
|
||||
// # CLick in the show-more button
|
||||
cy.get('[data-testid="rhs-runs-list"] > button').click();
|
||||
|
||||
// * Verify we have loaded the second page
|
||||
cy.get('[data-testid="rhs-runs-list"] > div').should('have.length', 10);
|
||||
});
|
||||
|
||||
it('card has the basic info', () => {
|
||||
// # Click the first run
|
||||
cy.get('[data-testid="rhs-runs-list"] > :nth-child(1)').within(() => {
|
||||
cy.findByText('playbook-run-9').should('be.visible');
|
||||
cy.findByText('The playbook name').should('be.visible');
|
||||
cy.findByText(testUser.username).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('can click though', () => {
|
||||
// # Click the first run
|
||||
cy.get('[data-testid="rhs-runs-list"] > :nth-child(1)').click();
|
||||
|
||||
// * Verify we made it to the run details at Channels RHS
|
||||
cy.get('#rhsContainer').contains('playbook-run-9');
|
||||
cy.get('#rhsContainer').contains('Tasks');
|
||||
});
|
||||
|
||||
it('can see give feedback button', () => {
|
||||
// * Verify give feedback button exists and has the right URL
|
||||
cy.get('#rhsContainer').findByText('Give feedback').
|
||||
should('exist').
|
||||
and('have.attr', 'href').
|
||||
and('include', 'https://mattermost.com/pl/playbooks-feedback');
|
||||
});
|
||||
|
||||
describe('dotmenu', () => {
|
||||
it('can navigate to RDP', () => {
|
||||
// # Click the first run's dotmenu
|
||||
cy.get('[data-testid="rhs-runs-list"] > :nth-child(1)').findByRole('button').click();
|
||||
|
||||
// # Click on go to run
|
||||
cy.findByText('Go to run overview').click();
|
||||
|
||||
// * Assert we are in the run details page
|
||||
cy.url().should('include', '/playbooks/runs/');
|
||||
cy.url().should('include', '?from=channel_rhs_dotmenu');
|
||||
});
|
||||
|
||||
it('can navigate to PBE', () => {
|
||||
// # Click the first run's dotmenu
|
||||
cy.get('[data-testid="rhs-runs-list"] > :nth-child(1)').findByRole('button').click();
|
||||
|
||||
// # Click on go to polaybook
|
||||
cy.findByText('Go to playbook').click();
|
||||
|
||||
// * Assert we are in the PBE page
|
||||
cy.url().should('include', `/playbooks/${testPlaybook.id}`);
|
||||
});
|
||||
|
||||
it('can change run name', () => {
|
||||
// # Click on the kebab menu
|
||||
cy.get('[data-testid="rhs-runs-list"] > :nth-child(1) .icon-dots-vertical').click();
|
||||
|
||||
// # Click on the rename run option
|
||||
cy.findByText('Rename run').click();
|
||||
|
||||
// # type new name
|
||||
cy.findByTestId('run-name-input').clear().type('My cool new run name');
|
||||
|
||||
// # click save
|
||||
cy.findByTestId('modal-confirm-button').click();
|
||||
|
||||
// * Verify the name has changed
|
||||
cy.get('[data-testid="rhs-runs-list"] > :nth-child(1)').contains('My cool new run name');
|
||||
});
|
||||
|
||||
it('can change linked channel', () => {
|
||||
// # Click on the kebab menu
|
||||
cy.get('[data-testid="rhs-runs-list"] > :nth-child(1) .icon-dots-vertical').click();
|
||||
|
||||
// # Click on the rename run option
|
||||
cy.findByText('Link run to a different channel').click();
|
||||
|
||||
// # type new name
|
||||
cy.get('.modal-body').within(() => {
|
||||
// # select town square
|
||||
cy.findByText(testChannel.display_name).click().type('Town Square{enter}');
|
||||
});
|
||||
|
||||
// # click save
|
||||
cy.findByTestId('modal-confirm-button').click();
|
||||
|
||||
// Let the listing refresh
|
||||
cy.wait(1000);
|
||||
|
||||
// * Verify we have the first page
|
||||
cy.get('[data-testid="rhs-runs-list"] > div').should('have.length', 8);
|
||||
|
||||
// # CLick in the show-more button
|
||||
cy.get('[data-testid="rhs-runs-list"] > button').click();
|
||||
|
||||
// * Verify the channel has changed, now one run less
|
||||
cy.get('[data-testid="rhs-runs-list"] > div').should('have.length', 9);
|
||||
});
|
||||
|
||||
describe('navigation', () => {
|
||||
let testChannelWith2Runs;
|
||||
before(() => {
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a test channel
|
||||
cy.apiCreateChannel(testTeam.id, 'channel', 'Channel').then(({channel}) => {
|
||||
testChannelWith2Runs = channel;
|
||||
|
||||
// # Run the playbook a few times in the existing channel
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const runName = 'playbook-run-' + i;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
ownerUserId: testUser.id,
|
||||
channelId: testChannelWith2Runs.id,
|
||||
playbookRunName: runName,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('stays at list even if one only linked run after moving run', () => {
|
||||
// # Visit channel with 2 runs
|
||||
cy.visit(`/${testTeam.name}/channels/${testChannelWith2Runs.name}`);
|
||||
|
||||
// # Click on the kebab menu
|
||||
cy.get('[data-testid="rhs-runs-list"] > :nth-child(1) .icon-dots-vertical').click();
|
||||
|
||||
// # Click on the rename run option
|
||||
cy.findByText('Link run to a different channel').click();
|
||||
|
||||
// # type new name
|
||||
cy.get('.modal-body').within(() => {
|
||||
// # select town square
|
||||
cy.findByText(testChannelWith2Runs.display_name).click().type('Town Square{enter}');
|
||||
});
|
||||
|
||||
// # click save
|
||||
cy.findByTestId('modal-confirm-button').click();
|
||||
|
||||
// * Verify the run is not there, but we are still in the list (not rhs details)
|
||||
cy.get('[data-testid="rhs-runs-list"] > div').should('have.length', 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,590 @@
|
||||
// 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 rhs > start a run', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testChannel;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
cy.apiCreateChannel(testTeam.id, 'existing-channel', 'Existing Channel').then(({channel}) => {
|
||||
testChannel = channel;
|
||||
});
|
||||
});
|
||||
|
||||
const createPlaybook = ({channelNameTemplate, runSummaryTemplate, channelId, channelMode, title}) => {
|
||||
const runSummaryTemplateEnabled = Boolean(runSummaryTemplate);
|
||||
|
||||
// # Create a public playbook
|
||||
return cy.apiCreatePlaybook({
|
||||
title: title || 'Public Playbook',
|
||||
channelNameTemplate,
|
||||
runSummaryTemplate,
|
||||
runSummaryTemplateEnabled,
|
||||
channelMode,
|
||||
channelId,
|
||||
teamId: testTeam.id,
|
||||
makePublic: true,
|
||||
memberIDs: [testUser.id],
|
||||
createPublicPlaybookRun: true,
|
||||
}).then((playbook) => {
|
||||
cy.wrap(playbook);
|
||||
});
|
||||
};
|
||||
|
||||
describe('From RHS run list > ', () => {
|
||||
beforeEach(() => {
|
||||
// # intercepts telemetry
|
||||
cy.interceptTelemetry();
|
||||
});
|
||||
|
||||
describe('playbook configured as create new channel', () => {
|
||||
it('defaults', () => {
|
||||
// # Fill default values
|
||||
createPlaybook({
|
||||
title: 'Playbook title' + Date.now(),
|
||||
channelNameTemplate: 'Channel template',
|
||||
runSummaryTemplate: 'run summary template',
|
||||
channelMode: 'create_new_channel',
|
||||
}).then((playbook) => {
|
||||
// # Visit the selected playbook
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Click start a run button
|
||||
cy.findByTestId('rhs-runlist-start-run').click();
|
||||
|
||||
cy.get('#root-portal.modal-open').within(() => {
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert we are at playbooks tab
|
||||
cy.findByText('Select a playbook').should('be.visible');
|
||||
|
||||
// # Click on the playbook
|
||||
cy.findAllByText(playbook.title).eq(0).click();
|
||||
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert template name is filled
|
||||
cy.findByTestId('run-name-input').should('have.value', 'Channel template');
|
||||
|
||||
// * Assert summary template is filled
|
||||
cy.findByTestId('run-summary-input').should('have.value', 'run summary template');
|
||||
|
||||
// # Click start button
|
||||
cy.findByTestId('modal-confirm-button').click();
|
||||
});
|
||||
|
||||
// * Assert telemetry data
|
||||
cy.expectTelemetryToContain([{
|
||||
name: 'playbookrun_create',
|
||||
type: 'track',
|
||||
properties: {
|
||||
place: 'channels_rhs_runlist',
|
||||
playbookId: playbook.id,
|
||||
channelMode: 'create_new_channel',
|
||||
public: true,
|
||||
hasPlaybookChanged: true,
|
||||
hasNameChanged: false,
|
||||
hasSummaryChanged: false,
|
||||
hasChannelModeChanged: false,
|
||||
hasChannelIdChanged: false,
|
||||
hasPublicChanged: false,
|
||||
}},
|
||||
], {waitForCalls: 2});
|
||||
|
||||
// * Verify we are on the channel just created
|
||||
cy.url().should('include', `/${testTeam.name}/channels/channel-template`);
|
||||
|
||||
// * Verify channel name
|
||||
cy.get('h2').contains('Beginning of Channel template');
|
||||
|
||||
// * Verify run RHS
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
cy.contains('Channel template');
|
||||
cy.contains('run summary template');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('change title/summary', () => {
|
||||
// # Fill default values
|
||||
createPlaybook({
|
||||
title: 'Playbook title' + Date.now(),
|
||||
channelNameTemplate: 'Channel template',
|
||||
runSummaryTemplate: 'run summary template',
|
||||
channelMode: 'create_new_channel',
|
||||
}).then((playbook) => {
|
||||
// # Visit the selected playbook
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Click start a run button
|
||||
cy.findByTestId('rhs-runlist-start-run').click();
|
||||
|
||||
cy.get('#root-portal.modal-open').within(() => {
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert we are at playbooks tab
|
||||
cy.findByText('Select a playbook').should('be.visible');
|
||||
|
||||
// # Click on the playbook
|
||||
cy.findAllByText(playbook.title).eq(0).click();
|
||||
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert template are filled (and force wait to them)
|
||||
cy.findByTestId('run-name-input').should('have.value', 'Channel template');
|
||||
|
||||
// * Assert summary template is filled
|
||||
cy.findByTestId('run-summary-input').should('have.value', 'run summary template');
|
||||
|
||||
// # Fill run name
|
||||
cy.findByTestId('run-name-input').clear().type('Test Run Name');
|
||||
|
||||
// # Fill run summary
|
||||
cy.findByTestId('run-summary-input').clear().type('Test Run Summary');
|
||||
|
||||
// # Click start button
|
||||
cy.findByTestId('modal-confirm-button').click();
|
||||
});
|
||||
|
||||
// * Assert telemetry data
|
||||
cy.expectTelemetryToContain([{
|
||||
name: 'playbookrun_create',
|
||||
type: 'track',
|
||||
properties: {
|
||||
place: 'channels_rhs_runlist',
|
||||
playbookId: playbook.id,
|
||||
channelMode: 'create_new_channel',
|
||||
public: true,
|
||||
hasPlaybookChanged: true,
|
||||
hasNameChanged: true,
|
||||
hasSummaryChanged: true,
|
||||
hasChannelModeChanged: false,
|
||||
hasChannelIdChanged: false,
|
||||
hasPublicChanged: false,
|
||||
}},
|
||||
]);
|
||||
|
||||
// * Verify we are on the channel just created
|
||||
cy.url().should('include', `/${testTeam.name}/channels/test-run-name`);
|
||||
|
||||
// * Verify channel name
|
||||
cy.get('h2').contains('Beginning of Test Run Name');
|
||||
|
||||
// * Verify run RHS
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
cy.contains('Test Run Name');
|
||||
cy.contains('Test Run Summary');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('change to link to existing channel defaults to current channel', () => {
|
||||
// # Fill default values
|
||||
createPlaybook({
|
||||
title: 'Playbook title' + Date.now(),
|
||||
channelNameTemplate: 'Channel template',
|
||||
runSummaryTemplate: 'run summary template',
|
||||
channelMode: 'create_new_channel',
|
||||
}).then((playbook) => {
|
||||
// # Visit the town square channel
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Click start a run button
|
||||
cy.findByTestId('rhs-runlist-start-run').click();
|
||||
|
||||
cy.get('#root-portal.modal-open').within(() => {
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert we are at playbooks tab
|
||||
cy.findByText('Select a playbook').should('be.visible');
|
||||
|
||||
// # Click on the playbook
|
||||
cy.findAllByText(playbook.title).eq(0).click();
|
||||
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// # Change to link to existing channel
|
||||
cy.findByTestId('link-existing-channel-radio').click();
|
||||
|
||||
// * Assert current channel is selected
|
||||
cy.findByText('Town Square').should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('change to link to existing channel with already selected channel', () => {
|
||||
// # Fill default values
|
||||
createPlaybook({
|
||||
title: 'Playbook title' + Date.now(),
|
||||
channelNameTemplate: 'Channel template',
|
||||
runSummaryTemplate: 'run summary template',
|
||||
channelMode: 'create_new_channel',
|
||||
channelId: testChannel.id,
|
||||
}).then((playbook) => {
|
||||
// # Visit the town square channel
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Click start a run button
|
||||
cy.findByTestId('rhs-runlist-start-run').click();
|
||||
|
||||
cy.get('#root-portal.modal-open').within(() => {
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert we are at playbooks tab
|
||||
cy.findByText('Select a playbook').should('be.visible');
|
||||
|
||||
// # Click on the playbook
|
||||
cy.findAllByText(playbook.title).eq(0).click();
|
||||
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// # Change to link to existing channel
|
||||
cy.findByTestId('link-existing-channel-radio').click();
|
||||
|
||||
// * Assert selected channel is unchanged
|
||||
cy.findByText(testChannel.display_name).should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('change to link to existing channel', () => {
|
||||
// # Fill default values
|
||||
createPlaybook({
|
||||
title: 'Playbook title' + Date.now(),
|
||||
channelNameTemplate: 'Channel template',
|
||||
runSummaryTemplate: 'run summary template',
|
||||
channelMode: 'create_new_channel',
|
||||
}).then((playbook) => {
|
||||
// # Visit the selected playbook
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Click start a run button
|
||||
cy.findByTestId('rhs-runlist-start-run').click();
|
||||
|
||||
cy.get('#root-portal.modal-open').within(() => {
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert we are at playbooks tab
|
||||
cy.findByText('Select a playbook').should('be.visible');
|
||||
|
||||
// # Click on the playbook
|
||||
cy.findAllByText(playbook.title).eq(0).click();
|
||||
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// # Change to link to existing channel
|
||||
cy.findByTestId('link-existing-channel-radio').click();
|
||||
|
||||
// # Fill run name
|
||||
cy.findByTestId('run-name-input').clear().type('Test Run Name');
|
||||
|
||||
// # Select test channel instead of current channel
|
||||
cy.findByText('Town Square').click().type(`${testChannel.display_name}{enter}`);
|
||||
|
||||
// # Click start button
|
||||
cy.findByTestId('modal-confirm-button').click();
|
||||
});
|
||||
|
||||
// * Assert telemetry data
|
||||
cy.expectTelemetryToContain([{
|
||||
name: 'playbookrun_create',
|
||||
type: 'track',
|
||||
properties: {
|
||||
place: 'channels_rhs_runlist',
|
||||
playbookId: playbook.id,
|
||||
channelMode: 'link_existing_channel',
|
||||
hasPlaybookChanged: true,
|
||||
hasNameChanged: true,
|
||||
hasSummaryChanged: false,
|
||||
hasChannelModeChanged: true,
|
||||
hasChannelIdChanged: true,
|
||||
hasPublicChanged: false,
|
||||
}},
|
||||
]);
|
||||
|
||||
// * Verify we are on the existing channel
|
||||
cy.url().should('include', `/${testTeam.name}/channels/${testChannel.name}`);
|
||||
|
||||
// * Verify channel name
|
||||
cy.get('h2').contains(`Beginning of ${testChannel.display_name}`);
|
||||
|
||||
// * Verify run RHS
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
cy.contains('Test Run Name');
|
||||
cy.contains('run summary template');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('playbook configured as linked to existing channel', () => {
|
||||
it('defaults', () => {
|
||||
// # Fill default values
|
||||
createPlaybook({
|
||||
title: 'Playbook title' + Date.now(),
|
||||
channelNameTemplate: 'Channel template',
|
||||
runSummaryTemplate: 'run summary template',
|
||||
channelMode: 'link_existing_channel',
|
||||
channelId: testChannel.id,
|
||||
}).then((playbook) => {
|
||||
// # Visit the selected playbook
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Click start a run button
|
||||
cy.findByTestId('rhs-runlist-start-run').click();
|
||||
|
||||
cy.get('#root-portal.modal-open').within(() => {
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert we are at playbooks tab
|
||||
cy.findByText('Select a playbook').should('be.visible');
|
||||
|
||||
// # Click on the playbook
|
||||
cy.findAllByText(playbook.title).eq(0).click();
|
||||
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert template name is empty
|
||||
cy.findByTestId('run-name-input').should('be.empty');
|
||||
|
||||
// * Assert template summary is filled
|
||||
cy.findByTestId('run-summary-input').should('have.value', 'run summary template');
|
||||
|
||||
// # Fill run name
|
||||
cy.findByTestId('run-name-input').clear().type('Test Run Name');
|
||||
|
||||
// # Click start button
|
||||
cy.findByTestId('modal-confirm-button').click();
|
||||
});
|
||||
|
||||
// * Assert telemetry data
|
||||
cy.expectTelemetryToContain([{
|
||||
name: 'playbookrun_create',
|
||||
type: 'track',
|
||||
properties: {
|
||||
place: 'channels_rhs_runlist',
|
||||
playbookId: playbook.id,
|
||||
channelMode: 'link_existing_channel',
|
||||
hasPlaybookChanged: true,
|
||||
hasNameChanged: true,
|
||||
hasSummaryChanged: false,
|
||||
hasChannelModeChanged: false,
|
||||
hasChannelIdChanged: false,
|
||||
hasPublicChanged: false,
|
||||
}},
|
||||
]);
|
||||
|
||||
// * Verify we are on the existing channel
|
||||
cy.url().should('include', `/${testTeam.name}/channels/${testChannel.name}`);
|
||||
|
||||
// * Verify channel name
|
||||
cy.get('h2').contains(`Beginning of ${testChannel.display_name}`);
|
||||
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
// * Verify run RHS
|
||||
cy.contains('Test Run Name');
|
||||
cy.contains('run summary template');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('fill initially empty channel', () => {
|
||||
// # Fill default values
|
||||
createPlaybook({
|
||||
title: 'Playbook title' + Date.now(),
|
||||
channelNameTemplate: 'Channel template',
|
||||
runSummaryTemplate: 'run summary template',
|
||||
channelMode: 'link_existing_channel',
|
||||
}).then((playbook) => {
|
||||
// # Visit the selected playbook
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Click start a run button
|
||||
cy.findByTestId('rhs-runlist-start-run').click();
|
||||
|
||||
cy.get('#root-portal.modal-open').within(() => {
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert we are at playbooks tab
|
||||
cy.findByText('Select a playbook').should('be.visible');
|
||||
|
||||
// # Click on the playbook
|
||||
cy.findAllByText(playbook.title).eq(0).click();
|
||||
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert template name is empty
|
||||
cy.findByTestId('run-name-input').should('be.empty');
|
||||
|
||||
// * Assert template summary is filled
|
||||
cy.findByTestId('run-summary-input').should('have.value', 'run summary template');
|
||||
|
||||
// # Fill run name
|
||||
cy.findByTestId('run-name-input').clear().type('Test Run Name');
|
||||
|
||||
// # Fill Town square as the channel to be linked
|
||||
cy.findByText('Select a channel').click().type(`${testChannel.display_name}{enter}`);
|
||||
|
||||
// # Click start button
|
||||
cy.findByTestId('modal-confirm-button').click();
|
||||
});
|
||||
|
||||
// * Assert telemetry data
|
||||
cy.expectTelemetryToContain([{
|
||||
name: 'playbookrun_create',
|
||||
type: 'track',
|
||||
properties: {
|
||||
place: 'channels_rhs_runlist',
|
||||
playbookId: playbook.id,
|
||||
channelMode: 'link_existing_channel',
|
||||
hasPlaybookChanged: true,
|
||||
hasNameChanged: true,
|
||||
hasSummaryChanged: false,
|
||||
hasChannelModeChanged: false,
|
||||
hasChannelIdChanged: true,
|
||||
hasPublicChanged: false,
|
||||
}},
|
||||
]);
|
||||
|
||||
// * Verify we are on the existing channel
|
||||
cy.url().should('include', `/${testTeam.name}/channels/${testChannel.name}`);
|
||||
|
||||
// * Verify channel name
|
||||
cy.get('h2').contains(`Beginning of ${testChannel.display_name}`);
|
||||
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
// * Verify run RHS
|
||||
cy.contains('Test Run Name');
|
||||
cy.contains('run summary template');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('change to create new channel', () => {
|
||||
// # Fill default values
|
||||
createPlaybook({
|
||||
title: 'Playbook title' + Date.now(),
|
||||
channelNameTemplate: 'Channel template',
|
||||
runSummaryTemplate: 'run summary template',
|
||||
channelMode: 'link_existing_channel',
|
||||
channelId: testChannel.id,
|
||||
}).then((playbook) => {
|
||||
// # Visit the selected playbook
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Click start a run button
|
||||
cy.findByTestId('rhs-runlist-start-run').click();
|
||||
|
||||
cy.get('#root-portal.modal-open').within(() => {
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// * Assert we are at playbooks tab
|
||||
cy.findByText('Select a playbook').should('be.visible');
|
||||
|
||||
// # Click on the playbook
|
||||
cy.findAllByText(playbook.title).eq(0).click();
|
||||
|
||||
// # Wait the modal to render
|
||||
cy.wait(500);
|
||||
|
||||
// # Change to create new channel
|
||||
cy.findByTestId('create-channel-radio').click();
|
||||
|
||||
// # Fill run name
|
||||
cy.findByTestId('run-name-input').clear().type('Test Run Name');
|
||||
|
||||
// # Click start button
|
||||
cy.findByTestId('modal-confirm-button').click();
|
||||
});
|
||||
|
||||
// * Assert telemetry data
|
||||
cy.expectTelemetryToContain([{
|
||||
name: 'playbookrun_create',
|
||||
type: 'track',
|
||||
properties: {
|
||||
place: 'channels_rhs_runlist',
|
||||
playbookId: playbook.id,
|
||||
channelMode: 'create_new_channel',
|
||||
hasPlaybookChanged: true,
|
||||
hasNameChanged: true,
|
||||
hasSummaryChanged: false,
|
||||
hasChannelModeChanged: true,
|
||||
hasChannelIdChanged: false,
|
||||
hasPublicChanged: false,
|
||||
}},
|
||||
]);
|
||||
|
||||
// * Verify we are on the channel just created
|
||||
cy.url().should('include', `/${testTeam.name}/channels/test-run-name`);
|
||||
|
||||
// * Verify channel name
|
||||
cy.get('h2').contains('Beginning of Test Run Name');
|
||||
|
||||
cy.get('#rhsContainer').should('exist').within(() => {
|
||||
// * Verify run RHS
|
||||
cy.contains('Test Run Name');
|
||||
cy.contains('run summary template');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,498 @@
|
||||
// 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
|
||||
|
||||
/* eslint-disable no-only-tests/no-only-tests */
|
||||
|
||||
import * as TIMEOUTS from '../../../../fixtures/timeouts';
|
||||
|
||||
describe('channels > rhs > status update', () => {
|
||||
const defaultReminderMessage = '# Default reminder message';
|
||||
let testTeam;
|
||||
let testChannel;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
let testRun;
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, channel, user}) => {
|
||||
testTeam = team;
|
||||
testChannel = channel;
|
||||
testUser = user;
|
||||
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a public playbook
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook',
|
||||
userId: testUser,
|
||||
broadcastChannelIds: [testChannel.id],
|
||||
reminderTimerDefaultSeconds: 3600,
|
||||
reminderMessageTemplate: defaultReminderMessage,
|
||||
retrospectiveEnabled: false,
|
||||
broadcastEnabled: true,
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a new playbook run
|
||||
const now = Date.now();
|
||||
const name = 'Playbook Run (' + now + ')';
|
||||
const channelName = 'playbook-run-' + now;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName: name,
|
||||
ownerUserId: testUser.id,
|
||||
}).then((run) => {
|
||||
testRun = run;
|
||||
});
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${channelName}`);
|
||||
});
|
||||
|
||||
describe('post update dialog', () => {
|
||||
it('renders description correctly', () => {
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// * Check description
|
||||
cy.findByTestId('update_run_status_description').contains(`This update for the run ${testRun.name} will be broadcasted to one channel and one direct message.`);
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('description link navigates to run overview', () => {
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// # Click overview link
|
||||
cy.findByTestId('run-overview-link').click();
|
||||
});
|
||||
|
||||
// * Check that we are now in run overview page
|
||||
cy.url().should('include', `/playbooks/runs/${testRun.id}`);
|
||||
|
||||
// * Check that the run actions modal is already opened
|
||||
cy.findByRole('dialog', {name: /Run Actions/i}).should('exist');
|
||||
});
|
||||
|
||||
it('prevents posting an update message with only whitespace', () => {
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// # Type the invalid data
|
||||
cy.findByTestId('update_run_status_textbox').clear().type(' {enter} {enter} ');
|
||||
|
||||
// * Verify submit is disabled.
|
||||
cy.get('button.confirm').should('be.disabled');
|
||||
|
||||
// # 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');
|
||||
});
|
||||
|
||||
it('lets users with no access to the playbook post an update', () => {
|
||||
let channelName;
|
||||
const updateMessage = 'status update ' + Date.now();
|
||||
|
||||
// # Login as sysadmin and create a private playbook and a run
|
||||
cy.apiAdminLogin().then(({user: sysadmin}) => {
|
||||
// # Create a private playbook
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook - Private',
|
||||
memberIDs: [sysadmin.id], // Make it accesible only to sysadmin
|
||||
inviteUsersEnabled: true,
|
||||
invitedUserIds: [testUser.id], // Invite the test user
|
||||
}).then((playbook) => {
|
||||
// # Create a new playbook run
|
||||
const now = Date.now();
|
||||
const name = 'Playbook Run (' + now + ')';
|
||||
channelName = 'playbook-run-' + now;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: playbook.id,
|
||||
playbookRunName: name,
|
||||
ownerUserId: sysadmin.id,
|
||||
}).then((run) => {
|
||||
cy.apiAddUsersToRun(run.id, [testUser.id]);
|
||||
});
|
||||
});
|
||||
}).then(() => {
|
||||
// # Login as the test user
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${channelName}`);
|
||||
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// # Enter valid data
|
||||
cy.findByTestId('update_run_status_textbox').type(updateMessage);
|
||||
|
||||
// # 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(updateMessage).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('confirms finishing the run, and remembers changes and reminder when canceled', () => {
|
||||
const updateMessage = 'This is the update text to test with.';
|
||||
const reminderTime = '1 day';
|
||||
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get the dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// * Verify the first message is there.
|
||||
cy.findByTestId('update_run_status_textbox').within(() => {
|
||||
cy.findByText(defaultReminderMessage).should('exist');
|
||||
});
|
||||
|
||||
// # Type text to test for later
|
||||
cy.findByTestId('update_run_status_textbox').clear().type(updateMessage);
|
||||
|
||||
// # Set a new reminder to test for later
|
||||
cy.openReminderSelector();
|
||||
cy.selectReminderTime(reminderTime);
|
||||
|
||||
// # Mark the run as finished
|
||||
cy.findByTestId('mark-run-as-finished').click({force: true});
|
||||
|
||||
// # Submit the dialog.
|
||||
cy.get('button.confirm').click();
|
||||
});
|
||||
|
||||
// * Confirmation should appear
|
||||
cy.get('.modal-header').should('be.visible').contains('Confirm finish run');
|
||||
|
||||
// # Cancel
|
||||
cy.get('#cancelModalButton').click({force: true});
|
||||
|
||||
// * Verify post update has the same information
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// * Verify the message was remembered
|
||||
cy.findByTestId('update_run_status_textbox').within(() => {
|
||||
cy.findByText(updateMessage).should('exist');
|
||||
});
|
||||
|
||||
// * Verify the reminder was remembered
|
||||
cy.get('#reminder_timer_datetime').contains(reminderTime);
|
||||
|
||||
// * Marked run is still checked
|
||||
cy.findByTestId('mark-run-as-finished').within(() => {
|
||||
cy.get('[type="checkbox"]').should('be.checked');
|
||||
});
|
||||
|
||||
// # Submit the dialog.
|
||||
cy.get('button.confirm').click();
|
||||
});
|
||||
|
||||
// * Confirmation should appear
|
||||
cy.get('.modal-header').should('be.visible').contains('Confirm finish run');
|
||||
|
||||
// # Submit
|
||||
cy.get('#confirmModalButton').click({force: true});
|
||||
|
||||
// * Verify the status update was posted.
|
||||
cy.getStyledComponent('CustomPostContent').within(() => {
|
||||
cy.findByText(updateMessage).should('exist');
|
||||
});
|
||||
|
||||
// * Verify the run was finished.
|
||||
cy.getLastPost().contains(`@${testUser.username} marked ${testRun.name} as finished.`);
|
||||
});
|
||||
|
||||
describe('prevents user from losing changes', () => {
|
||||
it('cancel, go back and save', () => {
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// # Type the invalid data
|
||||
cy.findByTestId('update_run_status_textbox').clear().type('My valid and important changes that I don\'t want to lose');
|
||||
|
||||
// * Click cancel
|
||||
cy.findByTestId('modal-cancel-button').click();
|
||||
});
|
||||
|
||||
// * Go back from unsaved changes modal
|
||||
cy.get('#confirm-modal-light').within(() => {
|
||||
cy.findByTestId('modal-cancel-button').click();
|
||||
});
|
||||
|
||||
// # Delay in between the modal switch to ensure the
|
||||
// # animation has fully happened
|
||||
cy.wait(TIMEOUTS.TWO_SEC);
|
||||
|
||||
// # Submit the dialog.
|
||||
cy.get('button.confirm').click();
|
||||
|
||||
// * Verify that the Post update and unsaved changes modals have gone.
|
||||
cy.getStatusUpdateDialog().should('not.exist');
|
||||
cy.get('#confirm-modal-light').should('not.exist');
|
||||
});
|
||||
|
||||
it('click overview link, go back and save', () => {
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// # Type the invalid data
|
||||
cy.findByTestId('update_run_status_textbox').clear().type('My valid and important changes that I don\'t want to lose');
|
||||
|
||||
// # Click overview link
|
||||
cy.findByTestId('run-overview-link').click();
|
||||
});
|
||||
|
||||
// Verify that the confirmation modal is shown
|
||||
cy.get('#confirm-modal-light').within(() => {
|
||||
// * Go back from unsaved changes modal
|
||||
cy.findByTestId('modal-cancel-button').click();
|
||||
});
|
||||
|
||||
// # Delay in between the modal switch to ensure the
|
||||
// # animation has fully happened
|
||||
cy.wait(TIMEOUTS.TWO_SEC);
|
||||
|
||||
// # Submit the dialog.
|
||||
cy.get('button.confirm').click();
|
||||
|
||||
// * Verify that the Post update and unsaved changes modals have gone.
|
||||
cy.getStatusUpdateDialog().should('not.exist');
|
||||
cy.get('#confirm-modal-light').should('not.exist');
|
||||
});
|
||||
|
||||
it('cancel and discard explicitly', () => {
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// # Type the invalid data
|
||||
cy.findByTestId('update_run_status_textbox').clear().type('My valid and important changes that I don\'t want to lose');
|
||||
|
||||
// * Click cancel
|
||||
cy.findByTestId('modal-cancel-button').click();
|
||||
});
|
||||
|
||||
// * Discard explicitly from unsaved changes
|
||||
cy.get('#confirm-modal-light').within(() => {
|
||||
cy.get('button.confirm').click();
|
||||
});
|
||||
|
||||
// * Verify that the Post update and unsaved changes modals have gone.
|
||||
cy.getStatusUpdateDialog().should('not.exist');
|
||||
cy.get('#confirm-modal-light').should('not.exist');
|
||||
});
|
||||
|
||||
it('click overview link and discard explicitly', () => {
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// # Type the invalid data
|
||||
cy.findByTestId('update_run_status_textbox').clear().type('My valid and important changes that I don\'t want to lose');
|
||||
|
||||
// # Click overview link
|
||||
cy.findByTestId('run-overview-link').click();
|
||||
});
|
||||
|
||||
// * Discard explicitly from unsaved changes
|
||||
cy.get('#confirm-modal-light').within(() => {
|
||||
cy.get('button.confirm').click();
|
||||
});
|
||||
|
||||
// * Assert that we are at run overview page.
|
||||
cy.url().should('include', `/playbooks/runs/${testRun.id}`);
|
||||
|
||||
// * Verify that the Post update and unsaved changes modals have gone.
|
||||
cy.getStatusUpdateDialog().should('not.exist');
|
||||
cy.get('#confirm-modal-light').should('not.exist');
|
||||
|
||||
// * Verify that the run actions modal is opened.
|
||||
cy.findByRole('dialog', {name: /Run Actions/i}).should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('shows the last update in update message', () => {
|
||||
it('shows the default when we have not made an update before', () => {
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get the dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// * Verify the first message is there.
|
||||
cy.findByTestId('update_run_status_textbox').within(() => {
|
||||
cy.findByText(defaultReminderMessage).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('when we have made a previous update', () => {
|
||||
const now = Date.now();
|
||||
const firstMessage = 'Update - ' + now;
|
||||
|
||||
// # Create a first status update
|
||||
cy.updateStatus(firstMessage);
|
||||
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get the dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// * Verify the first message is there.
|
||||
cy.findByTestId('update_run_status_textbox').within(() => {
|
||||
cy.findByText(firstMessage).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('the default reminder', () => {
|
||||
it('shows the configured default when we have not made a previous update', () => {
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get the dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// * Verify the default is as expected
|
||||
cy.get('#reminder_timer_datetime').within(() => {
|
||||
cy.get('[class$=singleValue]').should('have.text', '1 hour');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('shows the last reminder we typed in: 15 minutes', () => {
|
||||
const now = Date.now();
|
||||
const firstMessage = 'Update - ' + now;
|
||||
|
||||
// # Create a first status update
|
||||
cy.updateStatus(firstMessage, '15 minutes');
|
||||
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get the dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// * Verify the default is as expected
|
||||
cy.get('#reminder_timer_datetime').within(() => {
|
||||
cy.get('[class$=singleValue]').should('have.text', '15 minutes');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('shows the last reminder we typed in: 90 minutes', () => {
|
||||
const now = Date.now();
|
||||
const firstMessage = 'Update - ' + now;
|
||||
|
||||
// # Create a first status update
|
||||
cy.updateStatus(firstMessage, '90 minutes');
|
||||
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get the dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// * Verify the default is as expected
|
||||
cy.get('#reminder_timer_datetime').within(() => {
|
||||
cy.get('[class$=singleValue]').should('have.text', '1 hour, 30 minutes');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('shows the last reminder we typed in: 7 days', () => {
|
||||
const now = Date.now();
|
||||
const firstMessage = 'Update - ' + now;
|
||||
|
||||
// # Create a first status update
|
||||
cy.updateStatus(firstMessage, '7 days');
|
||||
|
||||
// # Run the `/playbook update` slash command.
|
||||
cy.uiPostMessageQuickly('/playbook update');
|
||||
|
||||
// # Get the dialog modal.
|
||||
cy.getStatusUpdateDialog().within(() => {
|
||||
// * Verify the default is as expected
|
||||
cy.get('#reminder_timer_datetime').within(() => {
|
||||
cy.get('[class$=singleValue]').should('have.text', '7 days');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('playbook with disabled status updates', () => {
|
||||
before(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a public playbook
|
||||
cy.apiCreatePlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook',
|
||||
userId: testUser,
|
||||
broadcastChannelId: testChannel.id,
|
||||
statusUpdateEnabled: false,
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
});
|
||||
});
|
||||
|
||||
describe('omit status update dialog when status updates are disabled', () => {
|
||||
it('shows the default when we have not made an update before', () => {
|
||||
// * Check if RHS section is loaded
|
||||
cy.get('#rhs-about').should('exist');
|
||||
|
||||
// * Check if Post Update section is omitted
|
||||
cy.get('#rhs-post-update').should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
// 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 > rhs > template', () => {
|
||||
let team1;
|
||||
let testUser;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.apiAdminLogin().then(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
team1 = team;
|
||||
testUser = user;
|
||||
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('create playbook', () => {
|
||||
describe('open new playbook creation modal and navigates to playbooks', () => {
|
||||
it('after clicking on Use', () => {
|
||||
// # Switch to playbooks DM channel
|
||||
cy.visit(`/${team1.name}/messages/@playbooks`);
|
||||
|
||||
// * Checking the bot badge as an indicator of page
|
||||
// * stability / rendering finished
|
||||
cy.findByText('BOT').should('be.visible');
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Return first template (Blank)
|
||||
cy.contains('Blank').click();
|
||||
|
||||
// * Assert playbooks creation modal is shown.
|
||||
cy.get('#playbooks_create').should('exist');
|
||||
|
||||
// # Click create playbook button.
|
||||
cy.get('button[data-testid=modal-confirm-button]').click();
|
||||
|
||||
// * Assert expected playbook template title in outline.
|
||||
cy.findByTestId('playbook-editor-title').contains('Blank');
|
||||
});
|
||||
|
||||
it('after clicking on title', () => {
|
||||
// # Switch to playbooks DM channel
|
||||
cy.visit(`/${team1.name}/messages/@playbooks`);
|
||||
|
||||
// * Checking the bot badge as an indicator of page
|
||||
// * stability / rendering finished
|
||||
cy.findByText('BOT').should('be.visible');
|
||||
|
||||
// # Open playbooks RHS.
|
||||
cy.getPlaybooksAppBarIcon().should('be.visible').click();
|
||||
|
||||
// # Return first template (Blank)
|
||||
cy.contains('Use').click();
|
||||
|
||||
// * Assert playbooks creation modal is shown.
|
||||
cy.get('#playbooks_create').should('exist');
|
||||
|
||||
// # Click create playbook button.
|
||||
cy.get('button[data-testid=modal-confirm-button]').click();
|
||||
|
||||
// * Assert expected playbook template title in outline.
|
||||
cy.findByTestId('playbook-editor-title').contains('Blank');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,94 @@
|
||||
// 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 > rhs > title', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
let playbookRunChannelName;
|
||||
let testPlaybookRun;
|
||||
|
||||
const getHeaderTitle = () => cy.get('#rhsContainer').find('.sidebar--right__title');
|
||||
|
||||
before(() => {
|
||||
cy.apiInitSetup().then(({team, user}) => {
|
||||
testTeam = team;
|
||||
testUser = user;
|
||||
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Create a playbook
|
||||
cy.apiCreateTestPlaybook({
|
||||
teamId: testTeam.id,
|
||||
title: 'Playbook',
|
||||
userId: testUser.id,
|
||||
}).then((playbook) => {
|
||||
testPlaybook = playbook;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// # Login as testUser
|
||||
cy.apiLogin(testUser);
|
||||
|
||||
// # Size the viewport to show the RHS without covering posts.
|
||||
cy.viewport('macbook-13');
|
||||
|
||||
// # Run the playbook
|
||||
const now = Date.now();
|
||||
const playbookRunName = 'Playbook Run (' + now + ')';
|
||||
playbookRunChannelName = 'playbook-run-' + now;
|
||||
cy.apiRunPlaybook({
|
||||
teamId: testTeam.id,
|
||||
playbookId: testPlaybook.id,
|
||||
playbookRunName,
|
||||
ownerUserId: testUser.id,
|
||||
}).then((run) => {
|
||||
testPlaybookRun = run;
|
||||
});
|
||||
|
||||
// # Navigate directly to the application and the playbook run channel
|
||||
cy.visit(`/${testTeam.name}/channels/${playbookRunChannelName}`);
|
||||
});
|
||||
|
||||
it('has title', () => {
|
||||
// * Verify the title is displayed
|
||||
getHeaderTitle().contains('Run details');
|
||||
});
|
||||
|
||||
it('has following button', () => {
|
||||
// * Verify the following button is displayed
|
||||
getHeaderTitle().find('button.unfollowButton').contains('Following');
|
||||
|
||||
// * Verify the follow button is not displayed
|
||||
getHeaderTitle().find('button.followButton').should('not.exist');
|
||||
});
|
||||
|
||||
it('can stop following', () => {
|
||||
// # Click the following button
|
||||
getHeaderTitle().find('button.unfollowButton').click();
|
||||
|
||||
// * Verify the following button is not displayed
|
||||
getHeaderTitle().find('button.unfollowButton').should('not.exist');
|
||||
|
||||
// * Verify the follow button is displayed
|
||||
getHeaderTitle().find('button.followButton').contains('Follow');
|
||||
});
|
||||
|
||||
it('can navigate to RDP', () => {
|
||||
// # Click the title
|
||||
getHeaderTitle().findByTestId('rhs-title').click();
|
||||
|
||||
// * assert url is RDP
|
||||
cy.url().should('include', `/playbooks/runs/${testPlaybookRun.id}`);
|
||||
});
|
||||
});
|
||||
Ссылка в новой задаче
Block a user