From 212ac800a6e3c6407119249edfa70ce5e3a0edbd Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Fri, 5 May 2023 14:01:48 -0300 Subject: [PATCH] MM-52453: fix playbooks/edit_spec (#23208) * Refactor and fix edit_spec Refactor edit_spec into multiple discrete specs, fix various issues running the specs, and un-skip several tests that now pass. Fixes: https://mattermost.atlassian.net/browse/MM-52453 * remove skipped tests --- .../{edit_spec.js => edit/actions_spec.js} | 710 +---------------- .../playbooks/edit/checklists_spec.js | 187 +++++ .../playbooks/playbooks/edit/header_spec.js | 101 +++ .../playbooks/edit/task_actions_spec.js | 723 +++++++++--------- 4 files changed, 678 insertions(+), 1043 deletions(-) rename e2e-tests/cypress/tests/integration/playbooks/playbooks/{edit_spec.js => edit/actions_spec.js} (59%) create mode 100644 e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/checklists_spec.js create mode 100644 e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/header_spec.js diff --git a/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit_spec.js b/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/actions_spec.js similarity index 59% rename from e2e-tests/cypress/tests/integration/playbooks/playbooks/edit_spec.js rename to e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/actions_spec.js index bab7e9329c..76c20c30a5 100644 --- a/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit_spec.js +++ b/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/actions_spec.js @@ -11,8 +11,9 @@ /* eslint-disable no-only-tests/no-only-tests */ -import * as TIMEOUTS from '../../../fixtures/timeouts'; +import * as TIMEOUTS from '../../../../fixtures/timeouts'; +// assumes that E20 license is uploaded describe('playbooks > edit', {testIsolation: true}, () => { let testTeam; let testSysadmin; @@ -55,162 +56,6 @@ describe('playbooks > edit', {testIsolation: true}, () => { cy.apiLogin(testUser); }); - describe('checklists', () => { - describe('pre-assignee', () => { - it('user gets pre-assigned, added to invite user list, and invitations become enabled', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - cy.findByText('Outline').click(); - - cy.get('#actions').within(() => { - cy.get('#invite-users').within(() => { - // * Verify invitations are disabled and no invited user exists - cy.get('label input').should('not.be.checked'); - cy.get('.invite-users-selector__control'). - after('content'). - should('eq', ''); - }); - }); - - // # Pre-assign the user - cy.get('#checklists').within(() => { - // # Trigger assignee select menu - cy.findByText('Untitled task').trigger('mouseover'); - cy.findByTestId('hover-menu-edit-button').click(); - cy.findByText('Assignee...').click(); - - // * Verify that the assignee input is focused now - cy.focused(). - should('have.attr', 'type', 'text'). - should('have.attr', 'id'); - - // * Verify that the root of the assignee select menu exists - cy.focused().parents('.playbook-react-select'). - should('exist'). - within(() => { - // # Select the test user - cy.findByText('@' + testUser.username).click({force: true}); - }); - }); - - cy.reload(); - - cy.get('#checklists').within(() => { - // # Trigger assignee select menu - cy.findByText('Untitled task').trigger('mouseover'); - cy.findByTestId('hover-menu-edit-button').click(); - cy.findByText('@' + testUser.username).click(); - - // * Verify that the assignee input is focused now - cy.focused(). - should('have.attr', 'type', 'text'). - should('have.attr', 'id'); - - // * Verify that the root of the assignee select menu exists - cy.focused(). - parents('.playbook-react-select'). - should('exist'); - }); - - cy.get('#actions').within(() => { - cy.get('#invite-users').within(() => { - // * Verify invitations are enabled and a single user is invited - cy.get('label input').should('be.checked'); - cy.get('.invite-users-selector__control'). - after('content'). - should('eq', '1 SELECTED'); - }); - }); - }); - }); - - describe('slash command', () => { - it('autocompletes after clicking Command...', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - cy.findByText('Outline').click(); - - cy.get('#checklists').within(() => { - // # Open the slash command input on a step - cy.findByText('Untitled task').trigger('mouseover'); - cy.findByTestId('hover-menu-edit-button').click(); - cy.findByText('Command...').click(); - - // * Verify the slash command input field now has focus - // * and starts with a slash prefix. - cy.focused(). - should('have.attr', 'placeholder', 'Slash Command'). - should('have.value', '/'); - }); - - // * Verify the autocomplete prompt is open - cy.get('#suggestionList').should('exist'); - }); - - // current regression in BPE - // MM-44606 - it.skip('removes the input prompt when blurring with an empty slash command', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - cy.findByText('Outline').click(); - - cy.get('#checklists').within(() => { - // # Open the slash command input on a step - cy.findByText('Untitled task').trigger('mouseover'); - cy.findByTestId('hover-menu-edit-button').click(); - cy.findByText('Add slash command').click(); - - // * Verify the slash command input field now has focus - // * and starts with a slash prefix. - cy.findByPlaceholderText('Slash Command').should('have.focus'); - cy.findByPlaceholderText('Slash Command').should('have.value', '/'); - - cy.findByPlaceholderText('Slash Command').type('{backspace}'); - cy.findByPlaceholderText('Slash Command').blur(); - - cy.findByText('Add slash command').should('be.visible'); - }); - }); - - // current regression in BPE - // MM-44606 - it.skip('removes the input prompt when blurring with an invalid slash command', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - cy.findByText('Outline').click(); - - cy.get('#checklists').within(() => { - // # Open the slash command input on a step - cy.findByText('Untitled task').trigger('mouseover'); - cy.findByTestId('hover-menu-edit-button').click(); - cy.findByText('Add slash command').click(); - - // * Verify the slash command input field now has focus - // * and starts with a slash prefix. - cy.findByPlaceholderText('Slash Command').should('have.focus'); - cy.findByPlaceholderText('Slash Command').should('have.value', '/'); - - // # Blur the slash command without having typed anything more - cy.findByPlaceholderText('Slash Command').blur(); - - cy.findByText('Add slash command').should('be.visible'); - }); - }); - }); - }); - const commonActionTests = () => { describe('when a playbook run starts', () => { let testPlaybook; @@ -640,68 +485,6 @@ describe('playbooks > edit', {testIsolation: true}, () => { }); }); }); - - // BPE regression - // user is still shown in the selector - // with a 1 MEMBER badge - // MM-44635 - it.skip('removes invitation from users that are no longer in the team', () => { - let userToRemove; - let playbookId; - - // # Create a playbook with a user that is later removed from the team - cy.apiLogin(testSysadmin). - then(() => { - cy.apiCreateUser().then((result) => { - userToRemove = result.user; - cy.apiAddUserToTeam( - testTeam.id, - userToRemove.id, - ); - - // # Create a playbook with the user that will be removed from the team. - cy.apiCreatePlaybook({ - teamId: testTeam.id, - title: 'Playbook (' + Date.now() + ')', - createPublicPlaybookRun: true, - memberIDs: [testUser.id, testSysadmin.id], - invitedUserIds: [userToRemove.id], - inviteUsersEnabled: true, - }).then((playbook) => { - playbookId = playbook.id; - }); - - // # Remove user from the team - cy.apiDeleteUserFromTeam( - testTeam.id, - userToRemove.id, - ); - }); - }). - then(() => { - cy.apiLogin(testUser); - - // # Visit the selected playbook - cy.visit(`/playbooks/playbooks/${playbookId}/outline`); - - // # select the actions section - cy.contains('run summary template').dblclick(); - cy.findByRole('button', {name: /save/i}); - cy.reload(); - - cy.get('#actions').within(() => { - // # Open the invited users selector - cy.get('#invite-users').within(() => { - cy.openSelector(); - - // * Verify there is no member badge - cy.get('.invite-users-selector__control'). - after('content'). - should('eq', ''); - }); - }); - }); - }); }); describe('assign owner setting', () => { @@ -830,128 +613,6 @@ describe('playbooks > edit', {testIsolation: true}, () => { }); }); }); - - // BPE regression, - // owner assignment does not save - // MM-44647 - it.skip('persists the assigned owner even if the toggle is off', () => { - // # Visit the selected playbook - cy.visit(`/playbooks/playbooks/${testPlaybook.id}/outline`); - - // # select the actions section - cy.get('#assign-owner').within(() => { - // * Verify that the toggle is unchecked - cy.get('label input').should('not.be.checked'); - - // # Click on the toggle to enable the setting - cy.get('label input').click({force: true}); - - // * Verify that the toggle is checked - cy.get('label input').should('be.checked'); - - // # Open the owner selector - cy.openSelector(); - - // # Select a owner - cy.selectOwner(testUser2.username); - - // * Verify that the control shows the selected owner - cy.get('.assign-owner-selector__control').contains( - testUser2.username, - ); - - // # Click on the toggle to disable the setting - cy.get('label input').click({force: true}); - - // * Verify that the toggle is unchecked - cy.get('label input').should('not.be.checked'); - }); - - // # The toggle click above should have saved, - // # reload to check the outcome. - cy.reload(); - - cy.get('#assign-owner').within(() => { - // * Verify that the toggle is unchecked - cy.get('label input').should('not.be.checked'); - - // # Click on the toggle to enable the setting - cy.get('label input').click({force: true}); - - // * Verify that the toggle is checked - cy.get('label input').should('be.checked'); - - // * Verify that the control shows the selected owner - cy.get('.assign-owner-selector__control').contains( - testUser2.username, - ); - }); - }); - - // BPE regression - // removed user is not shown in the owner selector - // but the toggle remains on - // MM-44678 - it.skip('removes the owner and disables the setting if the user is no longer in the team', () => { - let userToRemove; - - // # Create a playbook with a user that is later removed from the team - cy.apiLogin(testSysadmin). - then(() => { - // # We need to increase the maximum number of users per team; otherwise, - // adding a new member to the team fails in CI - cy.apiCreateUser().then((result) => { - userToRemove = result.user; - cy.apiAddUserToTeam( - testTeam.id, - userToRemove.id, - ); - - // # Create a playbook with the user that will be removed from the team as - // the default owner - cy.apiCreatePlaybook({ - teamId: testTeam.id, - title: 'Playbook (' + Date.now() + ')', - createPublicPlaybookRun: true, - memberIDs: [testUser.id, testSysadmin.id], - defaultOwnerId: userToRemove.id, - defaultOwnerEnabled: true, - }); - - // # Remove user from the team - cy.apiDeleteUserFromTeam( - testTeam.id, - userToRemove.id, - ); - }); - }). - then(() => { - cy.apiLogin(testUser); - - // # Visit the selected playbook - cy.visit(`/playbooks/playbooks/${testPlaybook.id}/outline`); - - // # select the actions section - cy.contains('run summary template').dblclick(); - cy.findByRole('button', {name: /save/i}); - cy.reload(); - - cy.get('#assign-owner').within(() => { - // * Verify that the toggle is unchecked - cy.get('label input').should('not.be.checked'); - - // # Click on the toggle to enable the setting - cy.get('label input').click({force: true}); - - // * Verify that the control shows the selected owner - cy.get( - '.assign-owner-selector__control', - ).within(() => { - cy.findByText('Search for people'); - }); - }); - }); - }); }); }); }; @@ -1012,34 +673,6 @@ describe('playbooks > edit', {testIsolation: true}, () => { cy.get('button').should('be.disabled'); }); }); - - it.skip('can fill a channel and is persisted', () => { - cy.get('#actions #link-existing-channel').within(() => { - // # click radio - cy.get('input[type=radio]').click(); - - cy.findByText('Select a channel').click().type('Town{enter}'); - }); - - cy.reload(); - - // * wait for page to load - cy.get('h1').should('be.visible'); - - cy.get('#actions #create-new-channel').within(() => { - // * Verify that the toggle is unchecked and inputs are disabled - cy.get('input[type=radio]').eq(0).should('not.be.checked'); - cy.get('label input[type=radio]').should('be.disabled'); - cy.get('button').should('be.disabled'); - }); - - cy.get('#actions #link-existing-channel').within(() => { - // * Verify that the toggle is checked and input is enabled - cy.get('input[type=radio]').should('be.checked'); - cy.get('input[type=text]').should('not.be.disabled'); - cy.findByText('Town Square').should('exist'); - }); - }); }); }); @@ -1183,77 +816,46 @@ describe('playbooks > edit', {testIsolation: true}, () => { }); }); - it.skip('shows channel name when private broadcast channel configured and user is a member', () => { + it('shows channel name when private broadcast channel configured and user is a member', () => { // # Visit the selected playbook - cy.visit('/playbooks/playbooks/' + testPlaybook.id + '/edit'); + cy.visit('/playbooks/playbooks/' + testPlaybook.id + '/outline'); - // # Switch to Status updates tab - cy.get('#root').findByText('Status updates').click(); + // * Verify no channel is selected + cy.findByTestId('status-update-broadcast-channels').should( + 'have.text', + 'no channels', + ); - // # Click on the toggle to enable the setting - cy.get('#broadcast-channels').within(() => { - cy.get('label input').click({force: true}); + // # Open the broadcast channel widget + cy.findByTestId('status-update-broadcast-channels').click(); + + // # select a private channel + cy.get('#floating-ui-root').within(() => { + cy.get('input').type(`${testPrivateChannel.display_name}{enter}{esc}`); }); - // # Open the broadcast channel widget and select a public channel - cy.get('#playbook-automation-broadcast'). - click(). - type(testPrivateChannel.display_name + '{enter}', {delay: 200}); - - // # Save the playbook - cy.findByTestId('save_playbook').click(); + // * Verify placeholder text is present + cy.findByTestId('status-update-broadcast-channels').should( + 'have.text', + '1 channel', + ); // # Visit the selected playbook - cy.visit('/playbooks/playbooks/' + testPlaybook.id + '/edit'); - - // # Switch to Status updates tab - cy.get('#root').findByText('Status updates').click(); + cy.visit('/playbooks/playbooks/' + testPlaybook.id + '/outline'); // * Verify placeholder text is present - cy.get('#playbook-automation-broadcast').should( + cy.findByTestId('status-update-broadcast-channels').should( 'have.text', - testPrivateChannel.display_name, + '1 channel', ); - }); - it.skip('shows "Unknown channel" when private broadcast channel configured and user is not a member', () => { - // # Visit the selected playbook - cy.visit('/playbooks/playbooks/' + testPlaybook.id + '/edit'); + // # Open the broadcast channel widget + cy.findByTestId('status-update-broadcast-channels').click(); - // # Switch to Status updates tab - cy.get('#root').findByText('Status updates').click(); - - // # Click on the toggle to enable the setting - cy.get('#broadcast-channels').within(() => { - cy.get('label input').click({force: true}); + // * Verify channel name displayed + cy.get('#floating-ui-root').within(() => { + cy.findByText(testPrivateChannel.display_name).should('be.visible'); }); - - // # Open the broadcast channel widget and select the private channel - cy.get('#playbook-automation-broadcast'). - click(). - type(testPrivateChannel.display_name + '{enter}', {delay: 200}); - - // # Save the playbook - cy.findByTestId('save_playbook').click(); - - // # Browse to the private channel - cy.visit(`/${testTeam.name}/channels/${testPrivateChannel.name}`); - - // # Leave the private channel - cy.uiPostMessageQuickly('/leave'); - cy.get('#confirmModalButton').click(); - - // # Visit the selected playbook - cy.visit('/playbooks/playbooks/' + testPlaybook.id + '/edit'); - - // # Switch to Status updates tab - cy.get('#root').findByText('Status updates').click(); - - // * Verify placeholder text is present - cy.get('#playbook-automation-broadcast').should( - 'have.text', - 'Unknown Channel', - ); }); }); }); @@ -1294,65 +896,6 @@ describe('playbooks > edit', {testIsolation: true}, () => { }); }); - it.skip('allows selecting a category when enabled', () => { - cy.findByTestId('user-joins-channel-categorize').within(() => { - // * Verify that the toggle is unchecked - cy.get('label input').should('not.be.checked'); - - // # Click on the toggle to enable the setting - cy.get('label input').click({force: true}); - - // * Verify that the toggle is checked - cy.get('label input').should('be.checked'); - - // # Open the category selector - openCategorySelector(); - - // # Select a category - selectCategory('Favorites'); - - // * Verify that the control shows the selected category - cy.get('.channel-selector__control').contains('Favorites'); - }); - }); - - it.skip('allows changing the category', () => { - cy.findByTestId('user-joins-channel-categorize').within(() => { - // * Verify that the toggle is unchecked - cy.get('label input').should('not.be.checked'); - - // # Click on the toggle to enable the setting - cy.get('label').eq(1).click(); - - // * Verify that the toggle is checked - cy.get('label input').should('be.checked'); - - // # Open the channel selector - openCategorySelector(); - - // # Select a category - selectCategory('Favorites'); - - // * Verify that the control shows the selected category - cy.get('#playbook-automation-categorize-playbook-run .channel-selector__control').contains( - 'Favorites', - ); - - // # Open the channel selector - cy.get('#playbook-automation-categorize-playbook-run .channel-selector__control').click({ - force: true, - }); - - // # Select a new channel - selectCategory('Channels'); - - // * Verify that the control shows the selected channel - cy.get('#playbook-automation-categorize-playbook-run .channel-selector__control').contains( - 'Channels', - ); - }); - }); - it('persists the category even if the toggle is off', () => { cy.findByTestId('user-joins-channel-categorize').within(() => { // * Verify that the toggle is unchecked @@ -1470,6 +1013,9 @@ describe('playbooks > edit', {testIsolation: true}, () => { describe('retrospective enable / disable', () => { beforeEach(() => { + // # Login as testUser + cy.apiLogin(testUser); + // # Visit the selected playbook cy.visit(`/playbooks/playbooks/${testPlaybook.id}/outline`); }); @@ -1511,198 +1057,4 @@ describe('playbooks > edit', {testIsolation: true}, () => { }); }); }); - - describe('Edit playbook name', () => { - it('can be updated', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - - // # Open the title dropdown and Rename - cy.findByTestId('playbook-editor-title').click(); - cy.findByText('Rename').click(); - - // # Change the name and save - cy.findByTestId('rendered-editable-text').type('{selectAll}{del}renamed playbook'); - cy.findByRole('button', {name: /save/i}).click(); - - cy.reload(); - - // * Verify the modified name persists - cy.findByRole('button', {name: /renamed playbook/i}).should('exist'); - }); - - // BPE regression? - // no more unsaved changes modal - it.skip('update, leave and discard', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - cy.get('#edit-playbook').click(); - - // * edit - cy.findByTestId('playbook-title-description').click(); - cy.get('#playbook-edit-name-and-description-modal').should('exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByTestId('playbook-edit-name-input').clear().type('playbook updated name'); - - // * leave without save, show confirm modal and discard - cy.findByTestId('modal-cancel-button').click(); - cy.get('#playbook-edit-name-and-description-modal').should('not.exist'); - cy.get('#confirm-modal-light').should('exist'); - cy.findByTestId('modal-confirm-button').click(); - - // * check modals are hidden and name is not changed - cy.get('#playbook-edit-name-and-description-modal').should('not.exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByText('playbook updated name').should('not.exist'); - }); - - // BPE regression? - // no more unsaved changes modal - it.skip('update, leave and go back to edit', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - cy.get('#edit-playbook').click(); - - // * edit - cy.findByTestId('playbook-title-description').click(); - cy.get('#playbook-edit-name-and-description-modal').should('exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByTestId('playbook-edit-name-input').clear().type('playbook updated name'); - - // * leave without save, show confirm modal and cancel - cy.findByTestId('modal-cancel-button').click(); - cy.get('#playbook-edit-name-and-description-modal').should('not.exist'); - cy.get('#confirm-modal-light').should('exist'); - cy.findByTestId('modal-cancel-button').click(); - - // * check modals are hidden and name is not changed - cy.get('#playbook-edit-name-and-description-modal').should('exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByTestId('modal-confirm-button').click(); - - // * modals are hidden and text is changed - cy.get('#playbook-edit-name-and-description-modal').should('not.exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByText('playbook updated name').should('exist'); - }); - }); - - describe('Edit playbook description', () => { - it.skip('can be updated', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - cy.findByText(/customize this playbook's description/i).dblclick(); - cy.focused().type('{selectAll}{del}some new description{esc}'); - cy.findByRole('button', {name: /save/i}).click(); - - cy.reload(); - - cy.findByText('some new description').should('exist'); - }); - - // BPE regression? - // no more unsaved changes modal - it.skip('update, leave and discard', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - cy.get('#edit-playbook').click(); - - // * edit - cy.findByTestId('playbook-title-description').click(); - cy.get('#playbook-edit-name-and-description-modal').should('exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByTestId('playbook-edit-name-and-description-modal-description-textbox').clear().type('playbook updated desc'); - - // * leave without save, show confirm modal and discard - cy.findByTestId('modal-cancel-button').click(); - cy.get('#playbook-edit-name-and-description-modal').should('not.exist'); - cy.get('#confirm-modal-light').should('exist'); - cy.findByTestId('modal-confirm-button').click(); - - // * check modals are hidden and name is not changed - cy.get('#playbook-edit-name-and-description-modal').should('not.exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByText('playbook updated desc').should('not.exist'); - }); - - // BPE regression? - // no more unsaved changes modal - it.skip('update, leave and go back to edit', () => { - // # Open Playbooks - cy.visit('/playbooks/playbooks'); - - // # Start a blank playbook - cy.findByText('Blank').click(); - cy.get('#edit-playbook').click(); - - // * edit - cy.findByTestId('playbook-title-description').click(); - cy.get('#playbook-edit-name-and-description-modal').should('exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByTestId('playbook-edit-name-and-description-modal-description-textbox').clear().type('playbook updated desc'); - - // * leave without save, show confirm modal and cancel - cy.findByTestId('modal-cancel-button').click(); - cy.get('#playbook-edit-name-and-description-modal').should('not.exist'); - cy.get('#confirm-modal-light').should('exist'); - cy.findByTestId('modal-cancel-button').click(); - - // * check modals are hidden and name is not changed - cy.get('#playbook-edit-name-and-description-modal').should('exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByTestId('modal-confirm-button').click(); - - // * modals are hidden and text is changed - cy.get('#playbook-edit-name-and-description-modal').should('not.exist'); - cy.get('#confirm-modal-light').should('not.exist'); - cy.findByText('playbook updated desc').should('exist'); - }); - }); - - describe('Duplicate', () => { - let testPlaybook; - beforeEach(() => { - cy.apiCreateTestPlaybook({ - teamId: testTeam.id, - title: 'Playbook (' + Date.now() + ')', - userId: testUser.id, - }).then((playbook) => { - testPlaybook = playbook; - }); - }); - - it('can be duplicated', () => { - // # Visit the selected playbook - cy.visit(`/playbooks/playbooks/${testPlaybook.id}/outline`); - - // # Open the title dropdown and Duplicate - cy.findByTestId('playbook-editor-title').click(); - cy.findByText('Duplicate').click(); - - // * Verify that playbook got duplicated - cy.findByTestId('playbook-editor-header').within(() => { - cy.findByText('Copy of ' + testPlaybook.title).should('exist'); - }); - - // * Verify that the duplicated playbook is shown in the LHS - cy.findByTestId('Playbooks').within(() => { - cy.findByText('Copy of ' + testPlaybook.title).should('be.visible'); - }); - }); - }); }); diff --git a/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/checklists_spec.js b/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/checklists_spec.js new file mode 100644 index 0000000000..f894a5e68d --- /dev/null +++ b/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/checklists_spec.js @@ -0,0 +1,187 @@ +// 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 */ + +describe('playbooks > edit', {testIsolation: true}, () => { + let testUser; + + before(() => { + cy.apiInitSetup().then(({user}) => { + testUser = user; + }); + }); + + beforeEach(() => { + // # Login as testUser + cy.apiLogin(testUser); + }); + + describe('checklists', () => { + describe('pre-assignee', () => { + it('user gets pre-assigned, added to invite user list, and invitations become enabled', () => { + // # Open Playbooks + cy.visit('/playbooks/playbooks'); + + // # Start a blank playbook + cy.findByText('Blank').click(); + cy.findByText('Outline').click(); + + cy.get('#actions').within(() => { + cy.get('#invite-users').within(() => { + // * Verify invitations are disabled and no invited user exists + cy.get('label input').should('not.be.checked'); + cy.get('.invite-users-selector__control'). + after('content'). + should('eq', ''); + }); + }); + + // # Pre-assign the user + cy.get('#checklists').within(() => { + // # Trigger assignee select menu + cy.findByText('Untitled task').trigger('mouseover'); + cy.findByTestId('hover-menu-edit-button').click(); + cy.findByText('Assignee...').click(); + + // * Verify that the assignee input is focused now + cy.focused(). + should('have.attr', 'type', 'text'). + should('have.attr', 'id'); + + // * Verify that the root of the assignee select menu exists + cy.focused().parents('.playbook-react-select'). + should('exist'). + within(() => { + // # Select the test user + cy.findByText('@' + testUser.username).click(); + }); + }); + + cy.reload(); + + cy.get('#checklists').within(() => { + // # Trigger assignee select menu + cy.findByText('Untitled task').trigger('mouseover'); + cy.findByTestId('hover-menu-edit-button').click(); + cy.findByText('@' + testUser.username).click(); + + // * Verify that the assignee input is focused now + cy.focused(). + should('have.attr', 'type', 'text'). + should('have.attr', 'id'); + + // * Verify that the root of the assignee select menu exists + cy.focused(). + parents('.playbook-react-select'). + should('exist'); + }); + + cy.get('#actions').within(() => { + cy.get('#invite-users').within(() => { + // * Verify invitations are enabled and a single user is invited + cy.get('label input').should('be.checked'); + cy.get('.invite-users-selector__control'). + after('content'). + should('eq', '1 SELECTED'); + }); + }); + }); + }); + + describe('slash command', () => { + it('autocompletes after clicking Command...', () => { + // # Open Playbooks + cy.visit('/playbooks/playbooks'); + + // # Start a blank playbook + cy.findByText('Blank').click(); + cy.findByText('Outline').click(); + + cy.get('#checklists').within(() => { + // # Open the slash command input on a step + cy.findByText('Untitled task').trigger('mouseover'); + cy.findByTestId('hover-menu-edit-button').click(); + cy.findByText('Command...').click(); + + // * Verify the slash command input field now has focus + // * and starts with a slash prefix. + cy.focused(). + should('have.attr', 'placeholder', 'Slash Command'). + should('have.value', '/'); + }); + + // * Verify the autocomplete prompt is open + cy.get('#suggestionList').should('exist'); + }); + + it('resets when saving with an empty slash command', () => { + // # Open Playbooks + cy.visit('/playbooks/playbooks'); + + // # Start a blank playbook + cy.findByText('Blank').click(); + cy.findByText('Outline').click(); + + cy.get('#checklists').within(() => { + // # Open the slash command input on a step + cy.findByText('Untitled task').trigger('mouseover'); + cy.findByTestId('hover-menu-edit-button').click(); + cy.findByText('Command...').click(); + }); + + cy.get('#floating-ui-root').within(() => { + // * Verify the slash command input field now has focus + // * and starts with a slash prefix. + cy.findByPlaceholderText('Slash Command').should('have.focus'); + cy.findByPlaceholderText('Slash Command').should('have.value', '/'); + + cy.findByPlaceholderText('Slash Command').type('{backspace}'); + + // # Click the save button + cy.findByText('Save').click(); + }); + + // * Verify no slash command was saved + cy.findByText('Command...').should('be.visible'); + }); + + it('removes the input prompt when blurring with an invalid slash command', () => { + // # Open Playbooks + cy.visit('/playbooks/playbooks'); + + // # Start a blank playbook + cy.findByText('Blank').click(); + cy.findByText('Outline').click(); + + cy.get('#checklists').within(() => { + // # Open the slash command input on a step + cy.findByText('Untitled task').trigger('mouseover'); + cy.findByTestId('hover-menu-edit-button').click(); + cy.findByText('Command...').click(); + }); + + cy.get('#floating-ui-root').within(() => { + // * Verify the slash command input field now has focus + // * and starts with a slash prefix. + cy.findByPlaceholderText('Slash Command').should('have.focus'); + cy.findByPlaceholderText('Slash Command').should('have.value', '/'); + + // # Click the save button + cy.findByText('Save').click(); + }); + + // * Verify no slash command was saved + cy.findByText('Command...').should('be.visible'); + }); + }); + }); +}); diff --git a/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/header_spec.js b/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/header_spec.js new file mode 100644 index 0000000000..cf4643739e --- /dev/null +++ b/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/header_spec.js @@ -0,0 +1,101 @@ +// 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 */ + +describe('playbooks > edit', {testIsolation: true}, () => { + let testTeam; + let testUser; + + before(() => { + cy.apiInitSetup().then(({team, user}) => { + testTeam = team; + testUser = user; + }); + }); + + beforeEach(() => { + // # Login as testUser + cy.apiLogin(testUser); + }); + + describe('Edit playbook name', () => { + it('can be updated', () => { + // # Open Playbooks + cy.visit('/playbooks/playbooks'); + + // # Start a blank playbook + cy.findByText('Blank').click(); + + // # Open the title dropdown and Rename + cy.findByTestId('playbook-editor-title').click(); + cy.findByText('Rename').click(); + + // # Change the name and save + cy.findByTestId('rendered-editable-text').type('{selectAll}{del}renamed playbook'); + cy.findByRole('button', {name: /save/i}).click(); + + cy.reload(); + + // * Verify the modified name persists + cy.findByRole('button', {name: /renamed playbook/i}).should('exist'); + }); + }); + + describe('Edit playbook description', () => { + it('can be updated', () => { + // # Open Playbooks + cy.visit('/playbooks/playbooks'); + + // # Start a blank playbook + cy.findByText('Blank').click(); + cy.findByText(/customize this playbook's description/i).dblclick(); + cy.focused().type('{selectAll}{del}some new description'); + cy.findByRole('button', {name: /save/i}).click(); + + cy.reload(); + + cy.findByText('some new description').should('exist'); + }); + }); + + describe('Duplicate', () => { + let testPlaybook; + beforeEach(() => { + cy.apiCreateTestPlaybook({ + teamId: testTeam.id, + title: 'Playbook (' + Date.now() + ')', + userId: testUser.id, + }).then((playbook) => { + testPlaybook = playbook; + }); + }); + + it('can be duplicated', () => { + // # Visit the selected playbook + cy.visit(`/playbooks/playbooks/${testPlaybook.id}/outline`); + + // # Open the title dropdown and Duplicate + cy.findByTestId('playbook-editor-title').click(); + cy.findByText('Duplicate').click(); + + // * Verify that playbook got duplicated + cy.findByTestId('playbook-editor-header').within(() => { + cy.findByText('Copy of ' + testPlaybook.title).should('exist'); + }); + + // * Verify that the duplicated playbook is shown in the LHS + cy.findByTestId('Playbooks').within(() => { + cy.findByText('Copy of ' + testPlaybook.title).should('be.visible'); + }); + }); + }); +}); diff --git a/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/task_actions_spec.js b/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/task_actions_spec.js index 4aff99c32a..15442d7884 100644 --- a/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/task_actions_spec.js +++ b/e2e-tests/cypress/tests/integration/playbooks/playbooks/edit/task_actions_spec.js @@ -30,441 +30,436 @@ describe('playbooks > edit > task actions', {testIsolation: true}, () => { }); }); + let testPlaybook; beforeEach(() => { // # Login as testUser cy.apiLogin(testUser); + + // # Create a playbook + cy.apiCreatePlaybook({ + teamId: testTeam.id, + title: 'Playbook (' + Date.now() + ')', + checklists: [{ + title: 'Test Checklist', + items: [ + {title: 'Test Task'}, + ], + }], + memberIDs: [ + testUser.id, + ], + }).then((playbook) => { + testPlaybook = playbook; + + // # Visit the selected playbook + cy.visit(`/playbooks/playbooks/${testPlaybook.id}/outline`); + }); }); - describe('modal', () => { - let testPlaybook; + const editTask = () => { + cy.findByTestId('checkbox-item-container').within(() => { + cy.findByText('Test Task').trigger('mouseover'); + cy.findByTestId('hover-menu-edit-button').click(); + }); + }; - beforeEach(() => { - // # Create a playbook - cy.apiCreatePlaybook({ - teamId: testTeam.id, - title: 'Playbook (' + Date.now() + ')', - checklists: [{ - title: 'Test Checklist', - items: [ - {title: 'Test Task'}, - ], - }], - memberIDs: [ - testUser.id, - ], - }).then((playbook) => { - testPlaybook = playbook; + it('disallows no keywords', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); - // # Visit the selected playbook - cy.visit(`/playbooks/playbooks/${testPlaybook.id}/outline`); - }); + // Attempt to enable the trigger + cy.findByText('Mark the task as done').click(); + + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); + + // Verify no actions are configured + cy.findByText('Task Actions').should('exist'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); + + assert.deepEqual(trigger.keywords, []); + assert.deepEqual(trigger.user_ids, []); + assert.isFalse(actions.enabled); + }); + }); + + it('allows a single keyword', () => { + // # intercepts telemetry + cy.interceptTelemetry(); + + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); + + // Add a keyword + cy.get('.modal-body').within(() => { + cy.get('input').eq(0).type('keyword1{enter}', {force: true}); }); - const editTask = () => { - cy.findByTestId('checkbox-item-container').within(() => { - cy.findByText('Test Task').trigger('mouseover'); - cy.findByTestId('hover-menu-edit-button').click(); - }); - }; + // Enable the trigger + cy.findByText('Mark the task as done').click(); - it('disallows no keywords', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - // Attempt to enable the trigger - cy.findByText('Mark the task as done').click(); + // Verify configured actions + cy.findByText('1 action'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); - - // Verify no actions are configured - cy.findByText('Task Actions').should('exist'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - - assert.deepEqual(trigger.keywords, []); - assert.deepEqual(trigger.user_ids, []); - assert.isFalse(actions.enabled); - }); + assert.deepEqual(trigger.keywords, ['keyword1']); + assert.deepEqual(trigger.user_ids, []); + assert.isTrue(actions.enabled); }); - it('allows a single keyword', () => { - // # intercepts telemetry - cy.interceptTelemetry(); - - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); - - // Add a keyword - cy.get('.modal-body').within(() => { - cy.get('input').eq(0).type('keyword1{enter}', {force: true}); - }); - - // Enable the trigger - cy.findByText('Mark the task as done').click(); - - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); - - // Verify configured actions - cy.findByText('1 action'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - - assert.deepEqual(trigger.keywords, ['keyword1']); - assert.deepEqual(trigger.user_ids, []); - assert.isTrue(actions.enabled); - }); - - // # assert telemetry data - cy.expectTelemetryToContain([ - { - name: 'taskactions_updated', - type: 'track', - properties: { - playbook_id: testPlaybook.id, - }, + // # assert telemetry data + cy.expectTelemetryToContain([ + { + name: 'taskactions_updated', + type: 'track', + properties: { + playbook_id: testPlaybook.id, }, - ]); + }, + ]); + }); + + it('allows multiple keywords', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); + + // Add multiple keywords + cy.get('.modal-body').within(() => { + cy.get('input').eq(0).type('keyword1{enter}', {force: true}); + cy.get('input').eq(0).type('keyword2{enter}', {force: true}); }); - it('allows multiple keywords', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); + // Enable the trigger + cy.findByText('Mark the task as done').click(); - // Add multiple keywords - cy.get('.modal-body').within(() => { - cy.get('input').eq(0).type('keyword1{enter}', {force: true}); - cy.get('input').eq(0).type('keyword2{enter}', {force: true}); - }); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - // Enable the trigger - cy.findByText('Mark the task as done').click(); + // Verify configured actions + cy.findByText('1 action'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); + assert.deepEqual(trigger.keywords, ['keyword1', 'keyword2']); + assert.deepEqual(trigger.user_ids, []); + assert.isTrue(actions.enabled); + }); + }); - // Verify configured actions - cy.findByText('1 action'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); + it('allows multi-word phrases', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); - assert.deepEqual(trigger.keywords, ['keyword1', 'keyword2']); - assert.deepEqual(trigger.user_ids, []); - assert.isTrue(actions.enabled); - }); + // Add a phrase + cy.get('.modal-body').within(() => { + cy.get('input').eq(0).type('a phrase with multiple words{enter}', {force: true}); }); - it('allows multi-word phrases', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); + // Enable the trigger + cy.findByText('Mark the task as done').click(); - // Add a phrase - cy.get('.modal-body').within(() => { - cy.get('input').eq(0).type('a phrase with multiple words{enter}', {force: true}); - }); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - // Enable the trigger - cy.findByText('Mark the task as done').click(); + // Verify configured actions + cy.findByText('1 action'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); + assert.deepEqual(trigger.keywords, ['a phrase with multiple words']); + assert.deepEqual(trigger.user_ids, []); + assert.isTrue(actions.enabled); + }); + }); - // Verify configured actions - cy.findByText('1 action'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); + it('allows removing previously configured keywords', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); - assert.deepEqual(trigger.keywords, ['a phrase with multiple words']); - assert.deepEqual(trigger.user_ids, []); - assert.isTrue(actions.enabled); - }); + // Add multiple keywords + cy.get('.modal-body').within(() => { + cy.get('input').eq(0).type('keyword1{enter}', {force: true}); + cy.get('input').eq(0).type('keyword2{enter}', {force: true}); }); - it('allows removing previously configured keywords', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); + // Enable the trigger + cy.findByText('Mark the task as done').click(); - // Add multiple keywords - cy.get('.modal-body').within(() => { - cy.get('input').eq(0).type('keyword1{enter}', {force: true}); - cy.get('input').eq(0).type('keyword2{enter}', {force: true}); - }); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - // Enable the trigger - cy.findByText('Mark the task as done').click(); + // Re-open the dialog + cy.findByText('1 action').click(); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); - - // Re-open the dialog - cy.findByText('1 action').click(); - - // Remove one trigger keyword - cy.get('.modal-body').within(() => { - cy.findByText('keyword1').next().click(); - }); - - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); - - // Verify configured actions - cy.findByText('1 action'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - - assert.deepEqual(trigger.keywords, ['keyword2']); - assert.deepEqual(trigger.user_ids, []); - assert.isTrue(actions.enabled); - }); + // Remove one trigger keyword + cy.get('.modal-body').within(() => { + cy.findByText('keyword1').next().click(); }); - it('disables when all keywords removed', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - // Add multiple keywords - cy.get('.modal-body').within(() => { - cy.get('input').eq(0).type('keyword1{enter}', {force: true}); - cy.get('input').eq(0).type('keyword2{enter}', {force: true}); - }); + // Verify configured actions + cy.findByText('1 action'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - // Enable the trigger - cy.findByText('Mark the task as done').click(); + assert.deepEqual(trigger.keywords, ['keyword2']); + assert.deepEqual(trigger.user_ids, []); + assert.isTrue(actions.enabled); + }); + }); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); + it('disables when all keywords removed', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); - // Re-open the dialog - cy.findByText('1 action').click(); - - // Remove all trigger keywords - cy.get('.modal-body').within(() => { - cy.findByText('keyword1').next().click(); - cy.findByText('keyword2').next().click(); - }); - - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); - - // Verify configured actions - cy.findByText('Task Actions'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - - assert.deepEqual(trigger.keywords, []); - assert.deepEqual(trigger.user_ids, []); - assert.isFalse(actions.enabled); - }); + // Add multiple keywords + cy.get('.modal-body').within(() => { + cy.get('input').eq(0).type('keyword1{enter}', {force: true}); + cy.get('input').eq(0).type('keyword2{enter}', {force: true}); }); - it('disallows a user without keywords', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); + // Enable the trigger + cy.findByText('Mark the task as done').click(); - // Add a user - cy.get('.modal-body').within(() => { - cy.get('input').eq(1). - type('@' + testUser.username, {force: true}). - wait(TIMEOUTS.ONE_SEC). - type('{enter}', {force: true}); - }); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - // Attempt to enable the trigger - cy.findByText('Mark the task as done').click(); + // Re-open the dialog + cy.findByText('1 action').click(); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); - - // Verify no actions are configured - cy.findByText('Task Actions').should('exist'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - - assert.deepEqual(trigger.keywords, []); - assert.deepEqual(trigger.user_ids, [testUser.id]); - assert.isFalse(actions.enabled); - }); + // Remove all trigger keywords + cy.get('.modal-body').within(() => { + cy.findByText('keyword1').next().click(); + cy.findByText('keyword2').next().click(); }); - it('allows a single user', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - // Add a keyword - cy.get('.modal-body').within(() => { - cy.get('input').eq(0).type('keyword1{enter}', {force: true}); - }); + // Verify configured actions + cy.findByText('Task Actions'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - // Add a user - cy.get('.modal-body').within(() => { - cy.get('input').eq(1). - type('@' + testUser.username, {force: true}). - wait(TIMEOUTS.ONE_SEC). - type('{enter}', {force: true}); - }); + assert.deepEqual(trigger.keywords, []); + assert.deepEqual(trigger.user_ids, []); + assert.isFalse(actions.enabled); + }); + }); - // Attempt to enable the trigger - cy.findByText('Mark the task as done').click(); + it('disallows a user without keywords', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); - - // Verify configured actions and user - cy.findByText('1 action'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - - assert.deepEqual(trigger.keywords, ['keyword1']); - assert.deepEqual(trigger.user_ids, [testUser.id]); - assert.isTrue(actions.enabled); - }); + // Add a user + cy.get('.modal-body').within(() => { + cy.get('input').eq(1). + type('@' + testUser.username, {force: true}). + wait(TIMEOUTS.ONE_SEC). + type('{enter}', {force: true}); }); - it('allows configuring multiple users', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); + // Attempt to enable the trigger + cy.findByText('Mark the task as done').click(); - // Add a keyword - cy.get('.modal-body').within(() => { - cy.get('input').eq(0).type('keyword1{enter}', {force: true}); - }); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - // Add two users - cy.get('.modal-body').within(() => { - cy.get('input').eq(1). - type('@' + testUser.username, {force: true}). - wait(TIMEOUTS.ONE_SEC). - type('{enter}', {force: true}); - cy.get('input').eq(1). - type('@' + testUser2.username, {force: true}). - wait(TIMEOUTS.ONE_SEC). - type('{enter}', {force: true}); - }); + // Verify no actions are configured + cy.findByText('Task Actions').should('exist'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - // Attempt to enable the trigger - cy.findByText('Mark the task as done').click(); + assert.deepEqual(trigger.keywords, []); + assert.deepEqual(trigger.user_ids, [testUser.id]); + assert.isFalse(actions.enabled); + }); + }); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); + it('allows a single user', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); - // Verify configured actions and user - cy.findByText('1 action'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - - assert.deepEqual(trigger.keywords, ['keyword1']); - assert.deepEqual(trigger.user_ids, [testUser.id, testUser2.id]); - assert.isTrue(actions.enabled); - }); + // Add a keyword + cy.get('.modal-body').within(() => { + cy.get('input').eq(0).type('keyword1{enter}', {force: true}); }); - it('rejects unknown user', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); - - // Add a keyword - cy.get('.modal-body').within(() => { - cy.get('input').eq(0).type('keyword1{enter}', {force: true}); - }); - - // Type an unknown user - cy.get('.modal-body').within(() => { - cy.get('input').eq(1). - type('@unknown', {force: true}). - wait(TIMEOUTS.ONE_SEC). - type('{enter}', {force: true}); - }); - - // Click away - cy.get('.modal-body').click(); - - // Attempt to enable the trigger - cy.findByText('Mark the task as done').click(); - - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); - - // Verify configured actions and user - cy.findByText('1 action'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - - assert.deepEqual(trigger.keywords, ['keyword1']); - assert.deepEqual(trigger.user_ids, []); - assert.isTrue(actions.enabled); - }); + // Add a user + cy.get('.modal-body').within(() => { + cy.get('input').eq(1). + type('@' + testUser.username, {force: true}). + wait(TIMEOUTS.ONE_SEC). + type('{enter}', {force: true}); }); - it('allows removing previously configured users', () => { - // Open the task actions modal - editTask(); - cy.findByText('Task Actions').click(); + // Attempt to enable the trigger + cy.findByText('Mark the task as done').click(); - // Add a keyword - cy.get('.modal-body').within(() => { - cy.get('input').eq(0).type('keyword1{enter}', {force: true}); - }); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - // Add two users - cy.get('.modal-body').within(() => { - cy.get('input').eq(1). - type('@' + testUser.username, {force: true}). - wait(TIMEOUTS.ONE_SEC). - type('{enter}', {force: true}); - cy.get('input').eq(1). - type('@' + testUser2.username, {force: true}). - wait(TIMEOUTS.ONE_SEC). - type('{enter}', {force: true}); - }); + // Verify configured actions and user + cy.findByText('1 action'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); - // Attempt to enable the trigger - cy.findByText('Mark the task as done').click(); + assert.deepEqual(trigger.keywords, ['keyword1']); + assert.deepEqual(trigger.user_ids, [testUser.id]); + assert.isTrue(actions.enabled); + }); + }); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); + it('allows configuring multiple users', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); - // Re-open the dialog - cy.findByText('1 action').click(); + // Add a keyword + cy.get('.modal-body').within(() => { + cy.get('input').eq(0).type('keyword1{enter}', {force: true}); + }); - // Remove one user keyword - cy.get('.modal-body').within(() => { - cy.findByText(testUser.username).parent().parent().next().click(); - }); + // Add two users + cy.get('.modal-body').within(() => { + cy.get('input').eq(1). + type('@' + testUser.username, {force: true}). + wait(TIMEOUTS.ONE_SEC). + type('{enter}', {force: true}); + cy.get('input').eq(1). + type('@' + testUser2.username, {force: true}). + wait(TIMEOUTS.ONE_SEC). + type('{enter}', {force: true}); + }); - // Save the dialog - cy.findByTestId('modal-confirm-button').click(); + // Attempt to enable the trigger + cy.findByText('Mark the task as done').click(); - // Verify configured actions - cy.findByText('1 action'); - cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { - const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); - const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); - assert.deepEqual(trigger.keywords, ['keyword1']); - assert.deepEqual(trigger.user_ids, [testUser2.id]); - assert.isTrue(actions.enabled); - }); + // Verify configured actions and user + cy.findByText('1 action'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); + + assert.deepEqual(trigger.keywords, ['keyword1']); + assert.deepEqual(trigger.user_ids, [testUser.id, testUser2.id]); + assert.isTrue(actions.enabled); + }); + }); + + it('rejects unknown user', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); + + // Add a keyword + cy.get('.modal-body').within(() => { + cy.get('input').eq(0).type('keyword1{enter}', {force: true}); + }); + + // Type an unknown user + cy.get('.modal-body').within(() => { + cy.get('input').eq(1). + type('@unknown', {force: true}). + wait(TIMEOUTS.ONE_SEC). + type('{enter}', {force: true}); + }); + + // Click away + cy.get('.modal-body').click(); + + // Attempt to enable the trigger + cy.findByText('Mark the task as done').click(); + + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); + + // Verify configured actions and user + cy.findByText('1 action'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); + + assert.deepEqual(trigger.keywords, ['keyword1']); + assert.deepEqual(trigger.user_ids, []); + assert.isTrue(actions.enabled); + }); + }); + + it('allows removing previously configured users', () => { + // Open the task actions modal + editTask(); + cy.findByText('Task Actions').click(); + + // Add a keyword + cy.get('.modal-body').within(() => { + cy.get('input').eq(0).type('keyword1{enter}', {force: true}); + }); + + // Add two users + cy.get('.modal-body').within(() => { + cy.get('input').eq(1). + type('@' + testUser.username, {force: true}). + wait(TIMEOUTS.ONE_SEC). + type('{enter}', {force: true}); + cy.get('input').eq(1). + type('@' + testUser2.username, {force: true}). + wait(TIMEOUTS.ONE_SEC). + type('{enter}', {force: true}); + }); + + // Attempt to enable the trigger + cy.findByText('Mark the task as done').click(); + + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); + + // Re-open the dialog + cy.findByText('1 action').click(); + + // Remove one user keyword + cy.get('.modal-body').within(() => { + cy.findByText(testUser.username).parent().parent().next().click(); + }); + + // Save the dialog + cy.findByTestId('modal-confirm-button').click(); + + // Verify configured actions + cy.findByText('1 action'); + cy.apiGetPlaybook(testPlaybook.id).then((playbook) => { + const trigger = JSON.parse(playbook.checklists[0].items[0].task_actions[0].trigger.payload); + const actions = JSON.parse(playbook.checklists[0].items[0].task_actions[0].actions[0].payload); + + assert.deepEqual(trigger.keywords, ['keyword1']); + assert.deepEqual(trigger.user_ids, [testUser2.id]); + assert.isTrue(actions.enabled); }); }); });