From 4e1b0cc3d22abed10db9e4eb4925f0d178177e1c Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 27 Jul 2023 11:46:27 +0300 Subject: [PATCH 1/2] Fix flaky test --- .../components/case_view_activity.test.tsx | 45 ------- .../case_view/components/user_list.test.tsx | 121 ++++++++++++++++-- .../case_view/components/user_list.tsx | 2 +- .../user_profiles/user_converter.ts | 2 +- x-pack/test/functional/services/cases/api.ts | 16 +-- .../services/cases/single_case_view.ts | 26 ++++ .../apps/cases/group1/view_case.ts | 77 ++++++++++- 7 files changed, 222 insertions(+), 67 deletions(-) diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx index ac699e081e773..23d704d996db4 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx @@ -451,51 +451,6 @@ describe('Case View Page activity tab', () => { }); describe('Case users', () => { - // FLAKY: https://github.com/elastic/kibana/issues/152204 - describe.skip('Participants', () => { - it('should render the participants correctly', async () => { - appMockRender = createAppMockRenderer(); - appMockRender.render(); - - const participantsSection = within( - await screen.findByTestId('case-view-user-list-participants') - ); - - expect(await participantsSection.findByText('Participant 1')).toBeInTheDocument(); - expect( - await participantsSection.findByText('participant_2@elastic.co') - ).toBeInTheDocument(); - expect(await participantsSection.findByText('participant_3')).toBeInTheDocument(); - expect(await participantsSection.findByText('P4')).toBeInTheDocument(); - expect(await participantsSection.findByText('Participant 5')).toBeInTheDocument(); - }); - - it('should render Unknown users correctly', async () => { - appMockRender = createAppMockRenderer(); - appMockRender.render(); - - const participantsSection = within( - await screen.findByTestId('case-view-user-list-participants') - ); - - expect(await participantsSection.findByText('Unknown')).toBeInTheDocument(); - }); - - it('should render assignees in the participants section', async () => { - appMockRender = createAppMockRenderer(); - appMockRender.render(); - - const participantsSection = within( - await screen.findByTestId('case-view-user-list-participants') - ); - - expect(await participantsSection.findByText('Unknown')).toBeInTheDocument(); - expect(await participantsSection.findByText('Fuzzy Marten')).toBeInTheDocument(); - expect(await participantsSection.findByText('elastic')).toBeInTheDocument(); - expect(await participantsSection.findByText('Misty Mackerel')).toBeInTheDocument(); - }); - }); - // FLAKY: https://github.com/elastic/kibana/issues/152206 describe.skip('Reporter', () => { it('should render the reporter correctly', async () => { diff --git a/x-pack/plugins/cases/public/components/case_view/components/user_list.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/user_list.test.tsx index 3176dbc1cdcc0..bcfb70cc2fe8c 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/user_list.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/user_list.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; +import { screen } from '@testing-library/react'; import { UserList } from './user_list'; import * as i18n from '../translations'; import { basicCase } from '../../../containers/mock'; @@ -13,6 +14,7 @@ import { useCaseViewNavigation } from '../../../common/navigation/hooks'; import type { AppMockRenderer } from '../../../common/mock'; import { createAppMockRenderer } from '../../../common/mock'; import userEvent from '@testing-library/user-event'; +import { userProfilesMap } from '../../../containers/user_profiles/api.mock'; jest.mock('../../../common/navigation/hooks'); @@ -39,7 +41,7 @@ describe('UserList ', () => { }); it('triggers mailto when email icon clicked', () => { - const result = appMockRender.render( + appMockRender.render( { /> ); - userEvent.click(result.getByTestId('user-list-email-button')); + userEvent.click(screen.getByTestId('user-list-email-button')); expect(open).toBeCalledWith( `mailto:${user.email}?subject=${i18n.EMAIL_SUBJECT(title)}&body=${i18n.EMAIL_BODY(caseLink)}`, @@ -60,28 +62,131 @@ describe('UserList ', () => { }); it('sort the users correctly', () => { - const result = appMockRender.render( + appMockRender.render( + ); + + const users = screen.getAllByTestId('user-profile-username'); + + expect(users[0].textContent).toBe('Cases'); + expect(users[1].textContent).toBe('elastic@elastic.co'); + expect(users[2].textContent).toBe('test'); + }); + + it('return null if no users', () => { + const result = appMockRender.render( + + ); + + expect(result.container).toBeEmptyDOMElement(); + }); + + it('shows the loading spinner if loading', () => { + appMockRender.render( + ); - const userProfiles = result.getAllByTestId('user-profile-username'); + expect(screen.getByTestId('users-list-loading-spinner')).toBeEmptyDOMElement(); + }); + + it('should render users with user profiles correctly', () => { + appMockRender.render( + + ); + + const userElement = screen.getByTestId('user-profile-username'); + expect(userElement.textContent).toBe('Damaged Raccoon'); + }); + + it('should not render invalid users', () => { + appMockRender.render( + + ); + + const users = screen.getAllByTestId('user-profile-username'); + + expect(users.length).toBe(1); + expect(users[0].textContent).toBe('Damaged Raccoon'); + }); + + it('should render Unknown users correctly', () => { + appMockRender.render( + + ); - expect(userProfiles[0].textContent).toBe('Cases'); - expect(userProfiles[1].textContent).toBe('elastic@elastic.co'); - expect(userProfiles[2].textContent).toBe('test'); + expect(screen.getByTestId('user-profile-username').textContent).toBe('Unknown'); }); }); diff --git a/x-pack/plugins/cases/public/components/case_view/components/user_list.tsx b/x-pack/plugins/cases/public/components/case_view/components/user_list.tsx index 96b4c80c723f9..69ddcd67cc769 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/user_list.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/user_list.tsx @@ -106,7 +106,7 @@ export const UserList: React.FC = React.memo( {loading && ( - + )} diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_converter.ts b/x-pack/plugins/cases/public/components/user_profiles/user_converter.ts index 9f76463672f52..12100eac75670 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/user_converter.ts +++ b/x-pack/plugins/cases/public/components/user_profiles/user_converter.ts @@ -25,7 +25,7 @@ export const convertToUserInfo = ( // we couldn't find a valid profile so let's try the username return createWithUsername(username, user); } else { - // didn't the username wasn't valid so we'll show an unknown user + // the username wasn't valid so we'll show an unknown user return { key: user.profileUid, userInfo: {} }; } } else if (isValidString(username)) { diff --git a/x-pack/test/functional/services/cases/api.ts b/x-pack/test/functional/services/cases/api.ts index 461f44a26da3c..9cd2466c007a8 100644 --- a/x-pack/test/functional/services/cases/api.ts +++ b/x-pack/test/functional/services/cases/api.ts @@ -24,7 +24,7 @@ import { User } from '../../../cases_api_integration/common/lib/authentication/t import { FtrProviderContext } from '../../ftr_provider_context'; import { generateRandomCaseWithoutConnector } from './helpers'; -type OmitSupertest = Omit; +type GetParams any> = Omit[0], 'supertest'>; export function CasesAPIServiceProvider({ getService }: FtrProviderContext) { const kbnSupertest = getService('supertest'); @@ -56,14 +56,8 @@ export function CasesAPIServiceProvider({ getService }: FtrProviderContext) { await deleteAllCaseItems(es); }, - async createAttachment({ - caseId, - params, - }: { - caseId: Parameters[0]['caseId']; - params: Parameters[0]['params']; - }): Promise { - return createComment({ supertest: kbnSupertest, params, caseId }); + async createAttachment(params: GetParams): Promise { + return createComment({ supertest: supertestWithoutAuth, ...params }); }, async setStatus( @@ -96,8 +90,8 @@ export function CasesAPIServiceProvider({ getService }: FtrProviderContext) { return suggestUserProfiles({ supertest: kbnSupertest, req: options }); }, - async getCase({ caseId }: OmitSupertest[0]>): Promise { - return getCase({ supertest: kbnSupertest, caseId }); + async getCase(params: GetParams): Promise { + return getCase({ supertest: supertestWithoutAuth, ...params }); }, async generateUserActions({ diff --git a/x-pack/test/functional/services/cases/single_case_view.ts b/x-pack/test/functional/services/cases/single_case_view.ts index 961ee05a33a52..cf27d4c2498d5 100644 --- a/x-pack/test/functional/services/cases/single_case_view.ts +++ b/x-pack/test/functional/services/cases/single_case_view.ts @@ -143,5 +143,31 @@ export function CasesSingleViewServiceProvider({ getService, getPageObject }: Ft await testSubjects.missingOrFail('euiSelectableList'); }); }, + + async refresh() { + await testSubjects.click('case-refresh'); + }, + + async getReporter() { + await testSubjects.existOrFail('case-view-user-list-reporter'); + + const reporter = await testSubjects.findAllDescendant( + 'user-profile-username', + await testSubjects.find('case-view-user-list-reporter') + ); + + return reporter[0]; + }, + + async getParticipants() { + await testSubjects.existOrFail('case-view-user-list-participants'); + + const participants = await testSubjects.findAllDescendant( + 'user-profile-username', + await testSubjects.find('case-view-user-list-participants') + ); + + return participants; + }, }; } diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts b/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts index cc8a8a751bcb0..9720ef5039dbc 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { v4 as uuidv4 } from 'uuid'; -import { CaseSeverity, CaseStatuses } from '@kbn/cases-plugin/common/types/domain'; +import { AttachmentType, CaseSeverity, CaseStatuses } from '@kbn/cases-plugin/common/types/domain'; import { setTimeout as setTimeoutAsync } from 'timers/promises'; import { FtrProviderContext } from '../../../ftr_provider_context'; @@ -971,6 +971,81 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { expect(lastBreadcrumb).to.be(theCase.title); }); }); + + describe('reporter', () => { + createOneCaseBeforeDeleteAllAfter(getPageObject, getService); + + it('should render the reporter correctly', async () => { + const reporter = await cases.singleCase.getReporter(); + + const reporterText = await reporter.getVisibleText(); + + expect(reporterText).to.be('elastic'); + }); + }); + + describe('participants', () => { + before(async () => { + await createUsersAndRoles(getService, users, roles); + await cases.api.activateUserProfiles([casesAllUser, casesAllUser2]); + }); + + afterEach(async () => { + await cases.api.deleteAllCases(); + }); + + after(async () => { + await cases.api.deleteAllCases(); + await deleteUsersAndRoles(getService, users, roles); + }); + + it('should render the participants correctly', async () => { + const theCase = await createAndNavigateToCase(getPageObject, getService); + await cases.api.createAttachment({ + caseId: theCase.id, + params: { + type: AttachmentType.user, + comment: 'test', + owner: 'cases', + }, + auth: { user: casesAllUser, space: 'default' }, + }); + + await cases.singleCase.refresh(); + await header.waitUntilLoadingHasFinished(); + + const participants = await cases.singleCase.getParticipants(); + + const casesAllUserText = await participants[0].getVisibleText(); + const elasticUserText = await participants[1].getVisibleText(); + + expect(casesAllUserText).to.be('cases all_user'); + expect(elasticUserText).to.be('elastic'); + }); + + it('should render assignees in the participants section', async () => { + await createAndNavigateToCase(getPageObject, getService); + + await cases.singleCase.openAssigneesPopover(); + await cases.common.setSearchTextInAssigneesPopover('case'); + await cases.common.selectFirstRowInAssigneesPopover(); + await cases.singleCase.closeAssigneesPopover(); + await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('user-profile-assigned-user-cases_all_user-remove-group'); + + const participants = await cases.singleCase.getParticipants(); + + expect(participants.length).to.be(3); + + const casesAllUserText = await participants[0].getVisibleText(); + const elasticUserText = await participants[1].getVisibleText(); + const testUserText = await participants[2].getVisibleText(); + + expect(casesAllUserText).to.be('cases all_user'); + expect(elasticUserText).to.be('elastic'); + expect(testUserText).to.be('test user'); + }); + }); }); }; From 7609e7d27a57df771c1bf7cc96ec117bfdc0a42f Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Fri, 28 Jul 2023 10:37:25 +0300 Subject: [PATCH 2/2] PR feedback and fix auth calls --- x-pack/test/functional/services/cases/api.ts | 17 +++++++++++------ .../apps/cases/group1/view_case.ts | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/x-pack/test/functional/services/cases/api.ts b/x-pack/test/functional/services/cases/api.ts index 9cd2466c007a8..59cfa4056364a 100644 --- a/x-pack/test/functional/services/cases/api.ts +++ b/x-pack/test/functional/services/cases/api.ts @@ -31,6 +31,15 @@ export function CasesAPIServiceProvider({ getService }: FtrProviderContext) { const es = getService('es'); const supertestWithoutAuth = getService('supertestWithoutAuth'); + const getSuperTest = (hasAuth: boolean) => (hasAuth ? supertestWithoutAuth : kbnSupertest); + + const createApiFunction = + any>(apiFunc: T) => + (params: GetParams): ReturnType => { + const supertest = getSuperTest(Boolean(params.auth)); + return apiFunc({ supertest, ...params }); + }; + return { async createCase(overwrites: Partial = {}): Promise { const caseData = { @@ -56,9 +65,7 @@ export function CasesAPIServiceProvider({ getService }: FtrProviderContext) { await deleteAllCaseItems(es); }, - async createAttachment(params: GetParams): Promise { - return createComment({ supertest: supertestWithoutAuth, ...params }); - }, + createAttachment: createApiFunction(createComment), async setStatus( caseId: string, @@ -90,9 +97,7 @@ export function CasesAPIServiceProvider({ getService }: FtrProviderContext) { return suggestUserProfiles({ supertest: kbnSupertest, req: options }); }, - async getCase(params: GetParams): Promise { - return getCase({ supertest: supertestWithoutAuth, ...params }); - }, + getCase: createApiFunction(getCase), async generateUserActions({ caseId, diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts b/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts index 9720ef5039dbc..f6cfbe1dc83c3 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/group1/view_case.ts @@ -995,7 +995,6 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); after(async () => { - await cases.api.deleteAllCases(); await deleteUsersAndRoles(getService, users, roles); }); @@ -1037,6 +1036,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { expect(participants.length).to.be(3); + // The assignee const casesAllUserText = await participants[0].getVisibleText(); const elasticUserText = await participants[1].getVisibleText(); const testUserText = await participants[2].getVisibleText();