diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index e36abd8d023e4..c83af688ed47f 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -400,6 +400,7 @@ enabled: - x-pack/performance/journeys/flight_dashboard.ts - x-pack/performance/journeys/login.ts - x-pack/performance/journeys/many_fields_discover.ts + - x-pack/performance/journeys/many_fields_transform.ts - x-pack/performance/journeys/promotion_tracking_dashboard.ts - x-pack/performance/journeys/web_logs_dashboard.ts - x-pack/performance/journeys/data_stress_test_lens.ts diff --git a/dev_docs/tutorials/performance/adding_performance_journey.mdx b/dev_docs/tutorials/performance/adding_performance_journey.mdx index 423619defd063..77bb7d6f39e53 100644 --- a/dev_docs/tutorials/performance/adding_performance_journey.mdx +++ b/dev_docs/tutorials/performance/adding_performance_journey.mdx @@ -12,7 +12,7 @@ In order to achieve our goal of creating best user experience in Kibana, it is i To make things easier, we introduced performance journeys, that mimics end-user experience with Kibana. Journey runs a flow of user interactions with Kibana in a browser and collects APM metrics for both server and client-side. -It is possible to instrument Kibana with [custom performance metrics](https://docs.elastic.dev/kibana-dev-docs/tutorials/performance/adding_custom_performance_metrics), +It is possible to instrument Kibana with [custom performance metrics](https://docs.elastic.dev/kibana-dev-docs/tutorial/performance/adding_custom_performance_metrics), that will provide more detailed information about feature performance. Journeys core is [kbn-journeys](packages/kbn-journeys/README.mdx) package. It is a function test by design and is powered @@ -61,7 +61,7 @@ Scripts steps include: You can skip warmup phase for debug purpose by using `--skip-warmup` flag -Since the tests are run on a local machine, there is also realistic throttling applied to the network to +Since the tests are run on a local machine, there is also realistic throttling applied to the network to simulate real life internet connection. This means that all requests have a fixed latency and limited bandwidth. ### Benchmarking performance on CI diff --git a/packages/kbn-journeys/journey/journey_ftr_harness.ts b/packages/kbn-journeys/journey/journey_ftr_harness.ts index bf5af70f3d698..1a227db49f11e 100644 --- a/packages/kbn-journeys/journey/journey_ftr_harness.ts +++ b/packages/kbn-journeys/journey/journey_ftr_harness.ts @@ -240,9 +240,8 @@ export class JourneyFtrHarness { return await block(); } - const span = this.apm?.startSpan(name, type ?? null, { - childOf: this.currentTransaction, - }); + const span = this.currentTransaction.startSpan(name, type ?? null); + if (!span) { return await block(); } diff --git a/x-pack/performance/journeys/many_fields_transform.ts b/x-pack/performance/journeys/many_fields_transform.ts new file mode 100644 index 0000000000000..24659d3cbfca8 --- /dev/null +++ b/x-pack/performance/journeys/many_fields_transform.ts @@ -0,0 +1,32 @@ +/* + * 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 { Journey } from '@kbn/journeys'; +import { subj } from '@kbn/test-subj-selector'; +import { waitForChrome } from '../utils'; + +export const journey = new Journey({ + kbnArchives: ['test/functional/fixtures/kbn_archiver/many_fields_data_view'], + esArchives: ['test/functional/fixtures/es_archiver/many_fields'], +}) + .step('Go to Transforms', async ({ page, kbnUrl }) => { + await page.goto(kbnUrl.get(`app/management/data/transform`)); + await waitForChrome(page); + await page.waitForSelector(subj('transformCreateFirstButton')); + await page.waitForSelector(subj('globalLoadingIndicator-hidden')); + }) + .step('Go to data view selection', async ({ page }) => { + const createButtons = page.locator(subj('transformCreateFirstButton')); + await createButtons.first().click(); + await page.waitForSelector(subj('savedObjectsFinderTable')); + }) + .step('Go to Transform Wizard', async ({ page }) => { + await page.click(subj('savedObjectTitleindices-stats*')); + // Extended the timeout, this one tracks a known issue with slow data grid performance with many fields + await page.waitForSelector(subj('transformIndexPreview loaded'), { timeout: 120000 }); + await page.waitForSelector(subj('globalLoadingIndicator-hidden'), { timeout: 120000 }); + }); diff --git a/x-pack/plugins/cases/common/api/cases/case.ts b/x-pack/plugins/cases/common/api/cases/case.ts index 80cf83b908aac..d9b0fd520757c 100644 --- a/x-pack/plugins/cases/common/api/cases/case.ts +++ b/x-pack/plugins/cases/common/api/cases/case.ts @@ -20,6 +20,9 @@ import { MAX_LENGTH_PER_TAG, MAX_CATEGORY_LENGTH, MAX_TAGS_PER_CASE, + MAX_ASSIGNEES_FILTER_LENGTH, + MAX_REPORTERS_FILTER_LENGTH, + MAX_TAGS_FILTER_LENGTH, } from '../../constants'; export const AttachmentTotalsRt = rt.strict({ @@ -220,7 +223,7 @@ export const CasesFindRequestRt = rt.exact( /** * Tags to filter by */ - tags: rt.union([rt.array(rt.string), rt.string]), + tags: rt.union([limitedArraySchema(rt.string, 0, MAX_TAGS_FILTER_LENGTH, 'tags'), rt.string]), /** * The status of the case (open, closed, in-progress) */ @@ -232,11 +235,17 @@ export const CasesFindRequestRt = rt.exact( /** * The uids of the user profiles to filter by */ - assignees: rt.union([rt.array(rt.string), rt.string]), + assignees: rt.union([ + limitedArraySchema(rt.string, 0, MAX_ASSIGNEES_FILTER_LENGTH, 'assignees'), + rt.string, + ]), /** * The reporters to filter by */ - reporters: rt.union([rt.array(rt.string), rt.string]), + reporters: rt.union([ + limitedArraySchema(rt.string, 0, MAX_REPORTERS_FILTER_LENGTH, 'reporters'), + rt.string, + ]), /** * Operator to use for the `search` field */ diff --git a/x-pack/plugins/cases/common/constants/index.ts b/x-pack/plugins/cases/common/constants/index.ts index 3ab7c59080b79..5607654b323ee 100644 --- a/x-pack/plugins/cases/common/constants/index.ts +++ b/x-pack/plugins/cases/common/constants/index.ts @@ -106,6 +106,9 @@ export const MAX_CONCURRENT_SEARCHES = 10 as const; export const MAX_BULK_GET_CASES = 1000 as const; export const MAX_COMMENTS_PER_PAGE = 100 as const; export const MAX_CATEGORY_FILTER_LENGTH = 100 as const; +export const MAX_TAGS_FILTER_LENGTH = 100 as const; +export const MAX_ASSIGNEES_FILTER_LENGTH = 100 as const; +export const MAX_REPORTERS_FILTER_LENGTH = 100 as const; /** * Validation diff --git a/x-pack/plugins/cases/docs/openapi/bundled.json b/x-pack/plugins/cases/docs/openapi/bundled.json index 70eef2b059c1d..51db7533403ca 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.json +++ b/x-pack/plugins/cases/docs/openapi/bundled.json @@ -3834,7 +3834,8 @@ "type": "array", "items": { "type": "string" - } + }, + "maxItems": 100 } ] } @@ -3930,7 +3931,8 @@ "type": "array", "items": { "type": "string" - } + }, + "maxItems": 100 } ] }, @@ -4031,7 +4033,8 @@ "type": "array", "items": { "type": "string" - } + }, + "maxItems": 100 } ] }, diff --git a/x-pack/plugins/cases/docs/openapi/bundled.yaml b/x-pack/plugins/cases/docs/openapi/bundled.yaml index 4c6aca7e63e3d..d2f570fc1b547 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.yaml +++ b/x-pack/plugins/cases/docs/openapi/bundled.yaml @@ -2326,6 +2326,7 @@ components: - type: array items: type: string + maxItems: 100 category: in: query name: category @@ -2392,6 +2393,7 @@ components: - type: array items: type: string + maxItems: 100 example: elastic search: in: query @@ -2463,6 +2465,7 @@ components: - type: array items: type: string + maxItems: 100 example: tag-1 to: in: query diff --git a/x-pack/plugins/cases/docs/openapi/components/parameters/assignees.yaml b/x-pack/plugins/cases/docs/openapi/components/parameters/assignees.yaml index 4ce794cbc879c..a4c81c67f6c67 100644 --- a/x-pack/plugins/cases/docs/openapi/components/parameters/assignees.yaml +++ b/x-pack/plugins/cases/docs/openapi/components/parameters/assignees.yaml @@ -9,4 +9,5 @@ schema: - type: string - type: array items: - type: string \ No newline at end of file + type: string + maxItems: 100 diff --git a/x-pack/plugins/cases/docs/openapi/components/parameters/reporters.yaml b/x-pack/plugins/cases/docs/openapi/components/parameters/reporters.yaml index 6fefa32f011dd..db28a6c48ae02 100644 --- a/x-pack/plugins/cases/docs/openapi/components/parameters/reporters.yaml +++ b/x-pack/plugins/cases/docs/openapi/components/parameters/reporters.yaml @@ -7,4 +7,5 @@ schema: - type: array items: type: string -example: elastic \ No newline at end of file + maxItems: 100 +example: elastic diff --git a/x-pack/plugins/cases/docs/openapi/components/parameters/tags.yaml b/x-pack/plugins/cases/docs/openapi/components/parameters/tags.yaml index bff378ac1fbda..d899edbcc38eb 100644 --- a/x-pack/plugins/cases/docs/openapi/components/parameters/tags.yaml +++ b/x-pack/plugins/cases/docs/openapi/components/parameters/tags.yaml @@ -7,4 +7,5 @@ schema: - type: array items: type: string -example: tag-1 \ No newline at end of file + maxItems: 100 +example: tag-1 diff --git a/x-pack/plugins/cases/server/client/cases/find.test.ts b/x-pack/plugins/cases/server/client/cases/find.test.ts index 968f111b58516..b7d9d9117ad7e 100644 --- a/x-pack/plugins/cases/server/client/cases/find.test.ts +++ b/x-pack/plugins/cases/server/client/cases/find.test.ts @@ -8,7 +8,12 @@ import { v1 as uuidv1 } from 'uuid'; import type { Case } from '../../../common/api'; -import { MAX_CATEGORY_FILTER_LENGTH } from '../../../common/constants'; +import { + MAX_ASSIGNEES_FILTER_LENGTH, + MAX_CATEGORY_FILTER_LENGTH, + MAX_REPORTERS_FILTER_LENGTH, + MAX_TAGS_FILTER_LENGTH, +} from '../../../common/constants'; import { flattenCaseSavedObject } from '../../common/utils'; import { mockCases } from '../../mocks'; import { createCasesClientMockArgs, createCasesClientMockFindRequest } from '../mocks'; @@ -114,5 +119,35 @@ describe('find', () => { `Error: Too many categories provided. The maximum allowed is ${MAX_CATEGORY_FILTER_LENGTH}` ); }); + + it(`throws an error when the tags array has ${MAX_TAGS_FILTER_LENGTH} items`, async () => { + const tags = Array(MAX_TAGS_FILTER_LENGTH + 1).fill('foobar'); + + const findRequest = createCasesClientMockFindRequest({ tags }); + + await expect(find(findRequest, clientArgs)).rejects.toThrowError( + `Error: The length of the field tags is too long. Array must be of length <= ${MAX_TAGS_FILTER_LENGTH}` + ); + }); + + it(`throws an error when the assignees array has ${MAX_ASSIGNEES_FILTER_LENGTH} items`, async () => { + const assignees = Array(MAX_ASSIGNEES_FILTER_LENGTH + 1).fill('foobar'); + + const findRequest = createCasesClientMockFindRequest({ assignees }); + + await expect(find(findRequest, clientArgs)).rejects.toThrowError( + `Error: The length of the field assignees is too long. Array must be of length <= ${MAX_ASSIGNEES_FILTER_LENGTH}` + ); + }); + + it(`throws an error when the reporters array has ${MAX_REPORTERS_FILTER_LENGTH} items`, async () => { + const reporters = Array(MAX_REPORTERS_FILTER_LENGTH + 1).fill('foobar'); + + const findRequest = createCasesClientMockFindRequest({ reporters }); + + await expect(find(findRequest, clientArgs)).rejects.toThrowError( + `Error: The length of the field reporters is too long. Array must be of length <= ${MAX_REPORTERS_FILTER_LENGTH}.` + ); + }); }); }); diff --git a/x-pack/plugins/transform/public/app/__mocks__/app_dependencies.tsx b/x-pack/plugins/transform/public/app/__mocks__/app_dependencies.tsx index c779fe577310e..da8fc9ede7344 100644 --- a/x-pack/plugins/transform/public/app/__mocks__/app_dependencies.tsx +++ b/x-pack/plugins/transform/public/app/__mocks__/app_dependencies.tsx @@ -71,6 +71,7 @@ dataStart.search.search = jest.fn(({ params }: IKibanaSearchRequest) => { }) as ISearchGeneric; const appDependencies: AppDependencies = { + analytics: coreStart.analytics, application: coreStart.application, charts: chartPluginMock.createStartContract(), chrome: coreStart.chrome, diff --git a/x-pack/plugins/transform/public/app/app_dependencies.tsx b/x-pack/plugins/transform/public/app/app_dependencies.tsx index 0830a741f45c6..d637fc706eb44 100644 --- a/x-pack/plugins/transform/public/app/app_dependencies.tsx +++ b/x-pack/plugins/transform/public/app/app_dependencies.tsx @@ -6,6 +6,7 @@ */ import type { + AnalyticsServiceStart, ApplicationStart, ChromeStart, DocLinksStart, @@ -15,12 +16,12 @@ import type { NotificationsStart, OverlayStart, SavedObjectsStart, + ScopedHistory, ThemeServiceStart, } from '@kbn/core/public'; import type { SavedObjectsStart as SavedObjectsPluginStart } from '@kbn/saved-objects-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; -import type { ScopedHistory } from '@kbn/core/public'; import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; @@ -38,6 +39,7 @@ import type { SettingsStart } from '@kbn/core-ui-settings-browser'; import type { GetMlSharedImportsReturnType } from '../shared_imports'; export interface AppDependencies { + analytics: AnalyticsServiceStart; application: ApplicationStart; charts: ChartsPluginStart; chrome: ChromeStart; diff --git a/x-pack/plugins/transform/public/app/hooks/use_index_data.ts b/x-pack/plugins/transform/public/app/hooks/use_index_data.ts index ef5c14265bd49..e3de879dfc40e 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_index_data.ts +++ b/x-pack/plugins/transform/public/app/hooks/use_index_data.ts @@ -5,11 +5,12 @@ * 2.0. */ -import { useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { EuiDataGridColumn } from '@elastic/eui'; +import { reportPerformanceMetricEvent } from '@kbn/ebt-tools'; import { isRuntimeMappings } from '@kbn/ml-runtime-field-utils'; import { buildBaseFilterCriteria } from '@kbn/ml-query-utils'; import { @@ -39,7 +40,7 @@ import { import { getErrorMessage } from '../../../common/utils/errors'; import { isDefaultQuery, matchAllQuery, TransformConfigQuery } from '../common'; -import { useToastNotifications } from '../app_dependencies'; +import { useToastNotifications, useAppDependencies } from '../app_dependencies'; import type { StepDefineExposedState } from '../sections/create_transform/components/step_define/common'; import { SearchItems } from './use_search_items'; @@ -52,6 +53,12 @@ export const useIndexData = ( combinedRuntimeMappings?: StepDefineExposedState['runtimeMappings'], timeRangeMs?: TimeRangeMs ): UseIndexDataReturnType => { + const { analytics } = useAppDependencies(); + + // Store the performance metric's start time using a ref + // to be able to track it across rerenders. + const loadIndexDataStartTime = useRef(window.performance.now()); + const indexPattern = useMemo(() => dataView.getIndexPattern(), [dataView]); const api = useApi(); @@ -315,6 +322,22 @@ export const useIndexData = ( const renderCellValue = useRenderCellValue(dataView, pagination, tableItems); + if ( + dataGrid.status === INDEX_STATUS.LOADED && + dataViewFields !== undefined && + loadIndexDataStartTime.current !== undefined + ) { + const loadIndexDataDuration = window.performance.now() - loadIndexDataStartTime.current; + + // Set this to undefined so reporting the metric gets triggered only once. + loadIndexDataStartTime.current = undefined; + + reportPerformanceMetricEvent(analytics, { + eventName: 'transformLoadIndexPreview', + duration: loadIndexDataDuration, + }); + } + return { ...dataGrid, renderCellValue, diff --git a/x-pack/plugins/transform/public/app/mount_management_section.ts b/x-pack/plugins/transform/public/app/mount_management_section.ts index 9568be198253e..f2b5663154e79 100644 --- a/x-pack/plugins/transform/public/app/mount_management_section.ts +++ b/x-pack/plugins/transform/public/app/mount_management_section.ts @@ -29,6 +29,7 @@ export async function mountManagementSection( const startServices = await getStartServices(); const [core, plugins] = startServices; const { + analytics, application, chrome, docLinks, @@ -61,6 +62,7 @@ export async function mountManagementSection( // AppCore/AppPlugins to be passed on as React context const appDependencies: AppDependencies = { + analytics, application, chrome, data, diff --git a/x-pack/plugins/transform/tsconfig.json b/x-pack/plugins/transform/tsconfig.json index 0103e7e4528c1..2be11c9b9d48f 100644 --- a/x-pack/plugins/transform/tsconfig.json +++ b/x-pack/plugins/transform/tsconfig.json @@ -65,7 +65,8 @@ "@kbn/ml-runtime-field-utils", "@kbn/ml-date-utils", "@kbn/saved-search-plugin", - "@kbn/unified-field-list" + "@kbn/unified-field-list", + "@kbn/ebt-tools" ], "exclude": [ "target/**/*", diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts index 00bdaa5b25f0b..6875bc043a6c5 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts @@ -8,7 +8,13 @@ import { v1 as uuidv1 } from 'uuid'; import expect from '@kbn/expect'; -import { CASES_URL, MAX_CATEGORY_FILTER_LENGTH } from '@kbn/cases-plugin/common/constants'; +import { + CASES_URL, + MAX_ASSIGNEES_FILTER_LENGTH, + MAX_CATEGORY_FILTER_LENGTH, + MAX_REPORTERS_FILTER_LENGTH, + MAX_TAGS_FILTER_LENGTH, +} from '@kbn/cases-plugin/common/constants'; import { Case, CaseSeverity, CaseStatuses, CommentType } from '@kbn/cases-plugin/common/api'; import { ALERTING_CASES_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -307,20 +313,6 @@ export default ({ getService }: FtrProviderContext): void => { }); }); - it('unhappy path - 400s when bad query supplied', async () => { - await findCases({ supertest, query: { perPage: true }, expectedHttpCode: 400 }); - }); - - for (const field of ['owner', 'tags', 'severity', 'status']) { - it(`should return a 400 when attempting to query a keyword field [${field}] when using a wildcard query`, async () => { - await findCases({ - supertest, - query: { searchFields: [field], search: 'some search string*' }, - expectedHttpCode: 400, - }); - }); - } - it('sorts by severity', async () => { const case4 = await createCase(supertest, { ...postCaseReq, @@ -349,10 +341,37 @@ export default ({ getService }: FtrProviderContext): void => { }); }); - it('unhappy path - 400s when more than the maximum category fields are supplied', async () => { - const category = Array(MAX_CATEGORY_FILTER_LENGTH + 1).fill('foobar'); + describe('errors', () => { + it('unhappy path - 400s when bad query supplied', async () => { + await findCases({ supertest, query: { perPage: true }, expectedHttpCode: 400 }); + }); + + for (const field of ['owner', 'tags', 'severity', 'status']) { + it(`should return a 400 when attempting to query a keyword field [${field}] when using a wildcard query`, async () => { + await findCases({ + supertest, + query: { searchFields: [field], search: 'some search string*' }, + expectedHttpCode: 400, + }); + }); + } - await findCases({ supertest, query: { category }, expectedHttpCode: 400 }); + for (const scenario of [ + { fieldName: 'category', sizeLimit: MAX_CATEGORY_FILTER_LENGTH }, + { fieldName: 'tags', sizeLimit: MAX_TAGS_FILTER_LENGTH }, + { fieldName: 'assignees', sizeLimit: MAX_ASSIGNEES_FILTER_LENGTH }, + { fieldName: 'reporters', sizeLimit: MAX_REPORTERS_FILTER_LENGTH }, + ]) { + it(`unhappy path - 400s when the field ${scenario.fieldName} exceeds the size limit`, async () => { + const value = Array(scenario.sizeLimit + 1).fill('foobar'); + + await findCases({ + supertest, + query: { [scenario.fieldName]: value }, + expectedHttpCode: 400, + }); + }); + } }); describe('search and searchField', () => { diff --git a/x-pack/test/functional/apps/infra/home_page.ts b/x-pack/test/functional/apps/infra/home_page.ts index 2274cd56baf37..98481732be9d5 100644 --- a/x-pack/test/functional/apps/infra/home_page.ts +++ b/x-pack/test/functional/apps/infra/home_page.ts @@ -225,41 +225,44 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); // FLAKY: https://github.com/elastic/kibana/issues/157740 - describe.skip('Saved Views', () => { + describe('Saved Views', () => { + this.tags('skipFirefox'); before(async () => { - esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); - await pageObjects.common.navigateToApp('infraOps'); - await pageObjects.infraHome.waitForLoading(); + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + await pageObjects.infraHome.goToMetricExplorer(); }); after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs')); + beforeEach(async () => { + await pageObjects.infraSavedViews.clickSavedViewsButton(); + }); + afterEach(async () => { + await pageObjects.infraSavedViews.closeSavedViewsPopover(); + }); + it('should render a button with the view name', async () => { await pageObjects.infraSavedViews.ensureViewIsLoaded('Default view'); }); it('should open/close the views popover menu on button click', async () => { await pageObjects.infraSavedViews.clickSavedViewsButton(); - testSubjects.existOrFail('savedViews-popover'); + await testSubjects.existOrFail('savedViews-popover'); await pageObjects.infraSavedViews.closeSavedViewsPopover(); }); it('should create a new saved view and load it', async () => { - await pageObjects.infraSavedViews.clickSavedViewsButton(); await pageObjects.infraSavedViews.createView('view1'); await pageObjects.infraSavedViews.ensureViewIsLoaded('view1'); }); - it('should laod a clicked view from the manage views section', async () => { - await pageObjects.infraSavedViews.clickSavedViewsButton(); - await pageObjects.infraSavedViews.ensureViewIsLoaded('view1'); + it('should load a clicked view from the manage views section', async () => { const views = await pageObjects.infraSavedViews.getManageViewsEntries(); await views[0].click(); await pageObjects.infraSavedViews.ensureViewIsLoaded('Default view'); }); it('should update the current saved view and load it', async () => { - await pageObjects.infraSavedViews.clickSavedViewsButton(); let views = await pageObjects.infraSavedViews.getManageViewsEntries(); expect(views.length).to.equal(2); await pageObjects.infraSavedViews.pressEsc(); @@ -267,6 +270,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.infraSavedViews.clickSavedViewsButton(); await pageObjects.infraSavedViews.createView('view2'); await pageObjects.infraSavedViews.ensureViewIsLoaded('view2'); + await pageObjects.infraSavedViews.clickSavedViewsButton(); views = await pageObjects.infraSavedViews.getManageViewsEntries(); expect(views.length).to.equal(3); @@ -275,6 +279,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.infraSavedViews.clickSavedViewsButton(); await pageObjects.infraSavedViews.updateView('view3'); await pageObjects.infraSavedViews.ensureViewIsLoaded('view3'); + await pageObjects.infraSavedViews.clickSavedViewsButton(); views = await pageObjects.infraSavedViews.getManageViewsEntries(); expect(views.length).to.equal(3);