mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Cases] Initial functional tests for cases in the stack management page (#127858)
* Adding data-test-subj to cases header component * adding casesApp service for functional tests * Adding test for create case * Add more tests * Add tests for cases list * Update tests file structure * Improve test structure * Add cleanup methods * Remove empty functions * Use api to create case to edit * move some repeated code to a service * Unify casesapp provider in a single namespace * Apply PR comment suggestions * Remove .only from test suite * Fix broken unit test * Attempt to fix flaky test * Another attempt to fix flaky test * Move checks up for flaky tests * increase timeout for flaky test * Try to fix flaky test * MOre fixes for flaky test * rename cases app and fix nitpicks * Rename variables * fix more nits * add more create case validatioons * add more create and edit case validations * Add extra validations to edit case * Fix typo * try to fix flaky test
This commit is contained in:
parent
5d519f3e72
commit
0dc168e086
14 changed files with 619 additions and 4 deletions
|
@ -88,7 +88,7 @@ export const CasesTable: FunctionComponent<CasesTableProps> = ({
|
|||
<EuiLoadingContent data-test-subj="initialLoadingPanelAllCases" lines={10} />
|
||||
</Div>
|
||||
) : (
|
||||
<Div>
|
||||
<Div data-test-subj={isCasesLoading ? 'cases-table-loading' : null}>
|
||||
<CasesTableUtilityBar
|
||||
data={data}
|
||||
enableBulkActions={showActions}
|
||||
|
|
|
@ -62,6 +62,7 @@ export interface HeaderPageProps extends HeaderProps {
|
|||
subtitle2?: SubtitleProps['items'];
|
||||
title: string | React.ReactNode;
|
||||
titleNode?: React.ReactElement;
|
||||
'data-test-subj'?: string;
|
||||
}
|
||||
|
||||
const HeaderPageComponent: React.FC<HeaderPageProps> = ({
|
||||
|
@ -73,6 +74,7 @@ const HeaderPageComponent: React.FC<HeaderPageProps> = ({
|
|||
subtitle2,
|
||||
title,
|
||||
titleNode,
|
||||
'data-test-subj': dataTestSubj,
|
||||
}) => {
|
||||
const { releasePhase } = useCasesContext();
|
||||
const { getAllCasesUrl, navigateToAllCases } = useAllCasesNavigation();
|
||||
|
@ -88,7 +90,7 @@ const HeaderPageComponent: React.FC<HeaderPageProps> = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<Header border={border}>
|
||||
<Header border={border} data-test-subj={dataTestSubj}>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<FlexItem>
|
||||
{showBackButton && (
|
||||
|
|
|
@ -46,15 +46,15 @@ Popover.displayName = 'Popover';
|
|||
|
||||
export interface UtilityBarActionProps extends LinkIconProps {
|
||||
popoverContent?: (closePopover: () => void) => React.ReactNode;
|
||||
dataTestSubj?: string;
|
||||
ownFocus?: boolean;
|
||||
dataTestSubj?: string;
|
||||
}
|
||||
|
||||
export const UtilityBarAction = React.memo<UtilityBarActionProps>(
|
||||
({
|
||||
dataTestSubj,
|
||||
children,
|
||||
color,
|
||||
dataTestSubj,
|
||||
disabled,
|
||||
href,
|
||||
iconSide,
|
||||
|
|
|
@ -119,6 +119,9 @@ export default async function ({ readConfigFile }) {
|
|||
logstashPipelines: {
|
||||
pathname: '/app/management/ingest/pipelines',
|
||||
},
|
||||
cases: {
|
||||
pathname: '/app/management/insightsAndAlerting/cases/',
|
||||
},
|
||||
maps: {
|
||||
pathname: '/app/maps',
|
||||
},
|
||||
|
|
45
x-pack/test/functional/services/cases/api.ts
Normal file
45
x-pack/test/functional/services/cases/api.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import pMap from 'p-map';
|
||||
import { CasePostRequest } from '../../../../plugins/cases/common/api';
|
||||
import { createCase, deleteAllCaseItems } from '../../../cases_api_integration/common/lib/utils';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { generateRandomCaseWithoutConnector } from './helpers';
|
||||
|
||||
export function CasesAPIServiceProvider({ getService }: FtrProviderContext) {
|
||||
const kbnSupertest = getService('supertest');
|
||||
const es = getService('es');
|
||||
|
||||
return {
|
||||
async createCaseWithData(overwrites: { title?: string } = {}) {
|
||||
const caseData = {
|
||||
...generateRandomCaseWithoutConnector(),
|
||||
...overwrites,
|
||||
} as CasePostRequest;
|
||||
await createCase(kbnSupertest, caseData);
|
||||
},
|
||||
|
||||
async createNthRandomCases(amount: number = 3) {
|
||||
const cases: CasePostRequest[] = Array.from(
|
||||
{ length: amount },
|
||||
() => generateRandomCaseWithoutConnector() as CasePostRequest
|
||||
);
|
||||
await pMap(
|
||||
cases,
|
||||
(caseData) => {
|
||||
return createCase(kbnSupertest, caseData);
|
||||
},
|
||||
{ concurrency: 4 }
|
||||
);
|
||||
},
|
||||
|
||||
async deleteAllCases() {
|
||||
deleteAllCaseItems(es);
|
||||
},
|
||||
};
|
||||
}
|
160
x-pack/test/functional/services/cases/common.ts
Normal file
160
x-pack/test/functional/services/cases/common.ts
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { WebElementWrapper } from 'test/functional/services/lib/web_element_wrapper';
|
||||
import uuid from 'uuid';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export function CasesCommonServiceProvider({ getService, getPageObject }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const find = getService('find');
|
||||
const comboBox = getService('comboBox');
|
||||
const header = getPageObject('header');
|
||||
return {
|
||||
/**
|
||||
* Opens the create case page pressing the "create case" button.
|
||||
*
|
||||
* Doesn't do navigation. Only works if you are already inside a cases app page.
|
||||
* Does not work with the cases flyout.
|
||||
*/
|
||||
async openCreateCasePage() {
|
||||
await testSubjects.click('createNewCaseBtn');
|
||||
await testSubjects.existOrFail('create-case-submit', {
|
||||
timeout: 5000,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* it creates a new case from the create case page
|
||||
* and leaves the navigation in the case view page
|
||||
*
|
||||
* Doesn't do navigation. Only works if you are already inside a cases app page.
|
||||
* Does not work with the cases flyout.
|
||||
*/
|
||||
async createCaseFromCreateCasePage({
|
||||
title = 'test-' + uuid.v4(),
|
||||
description = 'desc' + uuid.v4(),
|
||||
tag = 'tagme',
|
||||
}: {
|
||||
title: string;
|
||||
description: string;
|
||||
tag: string;
|
||||
}) {
|
||||
await this.openCreateCasePage();
|
||||
|
||||
// case name
|
||||
await testSubjects.setValue('input', title);
|
||||
|
||||
// case tag
|
||||
await comboBox.setCustom('comboBoxInput', tag);
|
||||
|
||||
// case description
|
||||
const descriptionArea = await find.byCssSelector('textarea.euiMarkdownEditorTextArea');
|
||||
await descriptionArea.focus();
|
||||
await descriptionArea.type(description);
|
||||
|
||||
// save
|
||||
await testSubjects.click('create-case-submit');
|
||||
|
||||
await testSubjects.existOrFail('case-view-title');
|
||||
},
|
||||
|
||||
/**
|
||||
* Goes to the first case listed on the table.
|
||||
*
|
||||
* This will fail if the table doesn't have any case
|
||||
*/
|
||||
async goToFirstListedCase() {
|
||||
await testSubjects.existOrFail('cases-table');
|
||||
await testSubjects.click('case-details-link');
|
||||
await testSubjects.existOrFail('case-view-title');
|
||||
},
|
||||
|
||||
/**
|
||||
* Marks a case in progress via the status dropdown
|
||||
*/
|
||||
async markCaseInProgressViaDropdown() {
|
||||
await this.openCaseSetStatusDropdown();
|
||||
|
||||
await testSubjects.click('case-view-status-dropdown-in-progress');
|
||||
|
||||
// wait for backend response
|
||||
await testSubjects.existOrFail('header-page-supplements > status-badge-in-progress', {
|
||||
timeout: 5000,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Marks a case closed via the status dropdown
|
||||
*/
|
||||
async markCaseClosedViaDropdown() {
|
||||
this.openCaseSetStatusDropdown();
|
||||
|
||||
await testSubjects.click('case-view-status-dropdown-closed');
|
||||
|
||||
// wait for backend response
|
||||
await testSubjects.existOrFail('header-page-supplements > status-badge-closed', {
|
||||
timeout: 5000,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Marks a case open via the status dropdown
|
||||
*/
|
||||
async markCaseOpenViaDropdown() {
|
||||
this.openCaseSetStatusDropdown();
|
||||
|
||||
await testSubjects.click('case-view-status-dropdown-open');
|
||||
|
||||
// wait for backend response
|
||||
await testSubjects.existOrFail('header-page-supplements > status-badge-open', {
|
||||
timeout: 5000,
|
||||
});
|
||||
},
|
||||
|
||||
async bulkDeleteAllCases() {
|
||||
await testSubjects.setCheckbox('checkboxSelectAll', 'check');
|
||||
const button = await find.byCssSelector('[aria-label="Bulk actions"]');
|
||||
await button.click();
|
||||
await testSubjects.click('cases-bulk-delete-button');
|
||||
await testSubjects.click('confirmModalConfirmButton');
|
||||
},
|
||||
|
||||
async selectAndDeleteAllCases() {
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.existOrFail('cases-table', { timeout: 20 * 1000 });
|
||||
let rows: WebElementWrapper[];
|
||||
do {
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.missingOrFail('cases-table-loading', { timeout: 5000 });
|
||||
rows = await find.allByCssSelector('[data-test-subj*="cases-table-row-"', 100);
|
||||
if (rows.length > 0) {
|
||||
await this.bulkDeleteAllCases();
|
||||
// wait for a second
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
} while (rows.length > 0);
|
||||
},
|
||||
|
||||
async validateCasesTableHasNthRows(nrRows: number) {
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.existOrFail('cases-table', { timeout: 20 * 1000 });
|
||||
await testSubjects.missingOrFail('cases-table-loading', { timeout: 5000 });
|
||||
const rows = await find.allByCssSelector('[data-test-subj*="cases-table-row-"', 100);
|
||||
expect(rows.length).equal(nrRows);
|
||||
},
|
||||
|
||||
async openCaseSetStatusDropdown() {
|
||||
const button = await find.byCssSelector(
|
||||
'[data-test-subj="case-view-status-dropdown"] button'
|
||||
);
|
||||
await button.click();
|
||||
},
|
||||
};
|
||||
}
|
26
x-pack/test/functional/services/cases/helpers.ts
Normal file
26
x-pack/test/functional/services/cases/helpers.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import uuid from 'uuid';
|
||||
|
||||
export function generateRandomCaseWithoutConnector() {
|
||||
return {
|
||||
title: 'random-' + uuid.v4(),
|
||||
tags: ['test', uuid.v4()],
|
||||
description: 'This is a description with id: ' + uuid.v4(),
|
||||
connector: {
|
||||
id: 'none',
|
||||
name: 'none',
|
||||
type: '.none',
|
||||
fields: null,
|
||||
},
|
||||
settings: {
|
||||
syncAlerts: false,
|
||||
},
|
||||
owner: 'cases',
|
||||
};
|
||||
}
|
17
x-pack/test/functional/services/cases/index.ts
Normal file
17
x-pack/test/functional/services/cases/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { CasesAPIServiceProvider } from './api';
|
||||
import { CasesCommonServiceProvider } from './common';
|
||||
|
||||
export function CasesServiceProvider(context: FtrProviderContext) {
|
||||
return {
|
||||
api: CasesAPIServiceProvider(context),
|
||||
common: CasesCommonServiceProvider(context),
|
||||
};
|
||||
}
|
|
@ -69,6 +69,7 @@ import {
|
|||
import { SearchSessionsService } from './search_sessions';
|
||||
import { ObservabilityProvider } from './observability';
|
||||
import { CompareImagesProvider } from './compare_images';
|
||||
import { CasesServiceProvider } from './cases';
|
||||
|
||||
// define the name and providers for services that should be
|
||||
// available to your tests. If you don't specify anything here
|
||||
|
@ -128,4 +129,5 @@ export const services = {
|
|||
searchSessions: SearchSessionsService,
|
||||
observability: ObservabilityProvider,
|
||||
compareImages: CompareImagesProvider,
|
||||
cases: CasesServiceProvider,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import uuid from 'uuid';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default ({ getPageObject, getService }: FtrProviderContext) => {
|
||||
describe('Create case', function () {
|
||||
const common = getPageObject('common');
|
||||
const find = getService('find');
|
||||
const cases = getService('cases');
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
before(async () => {
|
||||
await common.navigateToApp('cases');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await cases.api.deleteAllCases();
|
||||
});
|
||||
|
||||
it('creates a case from the stack management page', async () => {
|
||||
const caseTitle = 'test-' + uuid.v4();
|
||||
await cases.common.createCaseFromCreateCasePage({
|
||||
title: caseTitle,
|
||||
description: 'test description',
|
||||
tag: 'tagme',
|
||||
});
|
||||
|
||||
// validate title
|
||||
const title = await find.byCssSelector('[data-test-subj="header-page-title"]');
|
||||
expect(await title.getVisibleText()).equal(caseTitle);
|
||||
|
||||
// validate description
|
||||
const description = await testSubjects.find('user-action-markdown');
|
||||
expect(await description.getVisibleText()).equal('test description');
|
||||
|
||||
// validate tag exists
|
||||
await testSubjects.existOrFail('tag-tagme');
|
||||
|
||||
// validate no connector added
|
||||
const button = await find.byCssSelector('[data-test-subj*="case-callout"] button');
|
||||
expect(await button.getVisibleText()).equal('Add connector');
|
||||
});
|
||||
});
|
||||
};
|
169
x-pack/test/functional_with_es_ssl/apps/cases/edit_case_form.ts
Normal file
169
x-pack/test/functional_with_es_ssl/apps/cases/edit_case_form.ts
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import uuid from 'uuid';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default ({ getPageObject, getService }: FtrProviderContext) => {
|
||||
const common = getPageObject('common');
|
||||
const header = getPageObject('header');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const find = getService('find');
|
||||
const cases = getService('cases');
|
||||
const retry = getService('retry');
|
||||
const comboBox = getService('comboBox');
|
||||
|
||||
describe('Edit case', () => {
|
||||
// create the case to test on
|
||||
before(async () => {
|
||||
await common.navigateToApp('cases');
|
||||
await cases.api.createNthRandomCases(1);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await cases.api.deleteAllCases();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await common.navigateToApp('cases');
|
||||
await cases.common.goToFirstListedCase();
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
});
|
||||
|
||||
it('edits a case title from the case view page', async () => {
|
||||
const newTitle = `test-${uuid.v4()}`;
|
||||
|
||||
await testSubjects.click('editable-title-edit-icon');
|
||||
await testSubjects.setValue('editable-title-input-field', newTitle);
|
||||
await testSubjects.click('editable-title-submit-btn');
|
||||
|
||||
// wait for backend response
|
||||
await retry.tryForTime(5000, async () => {
|
||||
const title = await find.byCssSelector('[data-test-subj="header-page-title"]');
|
||||
expect(await title.getVisibleText()).equal(newTitle);
|
||||
});
|
||||
|
||||
// validate user action
|
||||
await find.byCssSelector('[data-test-subj*="title-update-action"]');
|
||||
});
|
||||
|
||||
it('adds a comment to a case', async () => {
|
||||
const commentArea = await find.byCssSelector(
|
||||
'[data-test-subj="add-comment"] textarea.euiMarkdownEditorTextArea'
|
||||
);
|
||||
await commentArea.focus();
|
||||
await commentArea.type('Test comment from automation');
|
||||
await testSubjects.click('submit-comment');
|
||||
|
||||
// validate user action
|
||||
const newComment = await find.byCssSelector(
|
||||
'[data-test-subj*="comment-create-action"] [data-test-subj="user-action-markdown"]'
|
||||
);
|
||||
expect(await newComment.getVisibleText()).equal('Test comment from automation');
|
||||
});
|
||||
|
||||
it('adds a tag to a case', async () => {
|
||||
const tag = uuid.v4();
|
||||
await testSubjects.click('tag-list-edit-button');
|
||||
await comboBox.setCustom('comboBoxInput', tag);
|
||||
await testSubjects.click('edit-tags-submit');
|
||||
|
||||
// validate tag was added
|
||||
await testSubjects.existOrFail('tag-' + tag);
|
||||
|
||||
// validate user action
|
||||
await find.byCssSelector('[data-test-subj*="tags-add-action"]');
|
||||
});
|
||||
|
||||
it('deletes a tag from a case', async () => {
|
||||
await testSubjects.click('tag-list-edit-button');
|
||||
// find the tag button and click the close button
|
||||
const button = await find.byCssSelector('[data-test-subj="comboBoxInput"] button');
|
||||
await button.click();
|
||||
await testSubjects.click('edit-tags-submit');
|
||||
|
||||
// validate user action
|
||||
await find.byCssSelector('[data-test-subj*="tags-delete-action"]');
|
||||
});
|
||||
|
||||
it('changes a case status to in-progress via dropdown menu', async () => {
|
||||
await cases.common.markCaseInProgressViaDropdown();
|
||||
// validate user action
|
||||
await find.byCssSelector(
|
||||
'[data-test-subj*="status-update-action"] [data-test-subj="status-badge-in-progress"]'
|
||||
);
|
||||
// validates dropdown tag
|
||||
await testSubjects.existOrFail('case-view-status-dropdown > status-badge-in-progress');
|
||||
});
|
||||
|
||||
it('changes a case status to closed via dropdown-menu', async () => {
|
||||
await cases.common.markCaseClosedViaDropdown();
|
||||
|
||||
// validate user action
|
||||
await find.byCssSelector(
|
||||
'[data-test-subj*="status-update-action"] [data-test-subj="status-badge-closed"]'
|
||||
);
|
||||
// validates dropdown tag
|
||||
await testSubjects.existOrFail('case-view-status-dropdown > status-badge-closed');
|
||||
});
|
||||
|
||||
it("reopens a case from the 'reopen case' button", async () => {
|
||||
await cases.common.markCaseClosedViaDropdown();
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.click('case-view-status-action-button');
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await testSubjects.existOrFail('header-page-supplements > status-badge-open', {
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
// validate user action
|
||||
await find.byCssSelector(
|
||||
'[data-test-subj*="status-update-action"] [data-test-subj="status-badge-open"]'
|
||||
);
|
||||
// validates dropdown tag
|
||||
await testSubjects.existOrFail('case-view-status-dropdown > status-badge-open');
|
||||
});
|
||||
|
||||
it("marks in progress a case from the 'mark in progress' button", async () => {
|
||||
await cases.common.markCaseOpenViaDropdown();
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.click('case-view-status-action-button');
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await testSubjects.existOrFail('header-page-supplements > status-badge-in-progress', {
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
// validate user action
|
||||
await find.byCssSelector(
|
||||
'[data-test-subj*="status-update-action"] [data-test-subj="status-badge-in-progress"]'
|
||||
);
|
||||
// validates dropdown tag
|
||||
await testSubjects.existOrFail('case-view-status-dropdown > status-badge-in-progress');
|
||||
});
|
||||
|
||||
it("closes a case from the 'close case' button", async () => {
|
||||
await cases.common.markCaseInProgressViaDropdown();
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.click('case-view-status-action-button');
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
||||
await testSubjects.existOrFail('header-page-supplements > status-badge-closed', {
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
// validate user action
|
||||
await find.byCssSelector(
|
||||
'[data-test-subj*="status-update-action"] [data-test-subj="status-badge-closed"]'
|
||||
);
|
||||
// validates dropdown tag
|
||||
await testSubjects.existOrFail('case-view-status-dropdown > status-badge-closed');
|
||||
});
|
||||
});
|
||||
};
|
17
x-pack/test/functional_with_es_ssl/apps/cases/index.ts
Normal file
17
x-pack/test/functional_with_es_ssl/apps/cases/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default ({ loadTestFile }: FtrProviderContext) => {
|
||||
describe('Cases', function () {
|
||||
this.tags('ciGroup27');
|
||||
loadTestFile(require.resolve('./create_case_form'));
|
||||
loadTestFile(require.resolve('./edit_case_form'));
|
||||
loadTestFile(require.resolve('./list_view'));
|
||||
});
|
||||
};
|
122
x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts
Normal file
122
x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import uuid from 'uuid';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default ({ getPageObject, getService }: FtrProviderContext) => {
|
||||
const common = getPageObject('common');
|
||||
const header = getPageObject('header');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const cases = getService('cases');
|
||||
const retry = getService('retry');
|
||||
const browser = getService('browser');
|
||||
|
||||
describe('cases list', () => {
|
||||
before(async () => {
|
||||
await common.navigateToApp('cases');
|
||||
await cases.api.deleteAllCases();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await cases.api.deleteAllCases();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await common.navigateToApp('cases');
|
||||
});
|
||||
|
||||
it('displays an empty list with an add button correctly', async () => {
|
||||
await testSubjects.existOrFail('cases-table-add-case');
|
||||
});
|
||||
|
||||
it('lists cases correctly', async () => {
|
||||
const NUMBER_CASES = 2;
|
||||
await cases.api.createNthRandomCases(NUMBER_CASES);
|
||||
await common.navigateToApp('cases');
|
||||
await cases.common.validateCasesTableHasNthRows(NUMBER_CASES);
|
||||
});
|
||||
|
||||
it('deletes a case correctly from the list', async () => {
|
||||
await cases.api.createNthRandomCases(1);
|
||||
await common.navigateToApp('cases');
|
||||
await testSubjects.click('action-delete');
|
||||
await testSubjects.click('confirmModalConfirmButton');
|
||||
await testSubjects.existOrFail('euiToastHeader');
|
||||
});
|
||||
|
||||
it('filters cases from the list with partial match', async () => {
|
||||
await cases.api.deleteAllCases();
|
||||
await cases.api.createNthRandomCases(5);
|
||||
const id = uuid.v4();
|
||||
const caseTitle = 'matchme-' + id;
|
||||
await cases.api.createCaseWithData({ title: caseTitle });
|
||||
await common.navigateToApp('cases');
|
||||
await testSubjects.missingOrFail('cases-table-loading', { timeout: 5000 });
|
||||
|
||||
// search
|
||||
const input = await testSubjects.find('search-cases');
|
||||
await input.type(caseTitle);
|
||||
await input.pressKeys(browser.keys.ENTER);
|
||||
|
||||
await retry.tryForTime(20000, async () => {
|
||||
await cases.common.validateCasesTableHasNthRows(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('paginates cases correctly', async () => {
|
||||
await cases.api.deleteAllCases();
|
||||
await cases.api.createNthRandomCases(8);
|
||||
await common.navigateToApp('cases');
|
||||
await testSubjects.click('tablePaginationPopoverButton');
|
||||
await testSubjects.click('tablePagination-5-rows');
|
||||
await testSubjects.isEnabled('pagination-button-1');
|
||||
await testSubjects.click('pagination-button-1');
|
||||
await testSubjects.isEnabled('pagination-button-0');
|
||||
});
|
||||
|
||||
it('bulk delete cases from the list', async () => {
|
||||
// deletes them from the API
|
||||
await cases.api.deleteAllCases();
|
||||
await cases.api.createNthRandomCases(8);
|
||||
await common.navigateToApp('cases');
|
||||
// deletes them from the UI
|
||||
await cases.common.selectAndDeleteAllCases();
|
||||
await cases.common.validateCasesTableHasNthRows(0);
|
||||
});
|
||||
|
||||
describe('changes status from the list', () => {
|
||||
before(async () => {
|
||||
await common.navigateToApp('cases');
|
||||
await cases.api.deleteAllCases();
|
||||
await cases.api.createNthRandomCases(1);
|
||||
await common.navigateToApp('cases');
|
||||
});
|
||||
|
||||
it('to in progress', async () => {
|
||||
await cases.common.openCaseSetStatusDropdown();
|
||||
await testSubjects.click('case-view-status-dropdown-in-progress');
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.existOrFail('status-badge-in-progress');
|
||||
});
|
||||
|
||||
it('to closed', async () => {
|
||||
await cases.common.openCaseSetStatusDropdown();
|
||||
await testSubjects.click('case-view-status-dropdown-closed');
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.existOrFail('status-badge-closed');
|
||||
});
|
||||
|
||||
it('to open', async () => {
|
||||
await cases.common.openCaseSetStatusDropdown();
|
||||
await testSubjects.click('case-view-status-dropdown-open');
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
await testSubjects.existOrFail('status-badge-open');
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -48,6 +48,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
resolve(__dirname, './apps/triggers_actions_ui'),
|
||||
resolve(__dirname, './apps/uptime'),
|
||||
resolve(__dirname, './apps/ml'),
|
||||
resolve(__dirname, './apps/cases'),
|
||||
],
|
||||
apps: {
|
||||
...xpackFunctionalConfig.get('apps'),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue