Skip to content

Commit

Permalink
Merge branch 'main' into move-structure-risk_engine_apis
Browse files Browse the repository at this point in the history
  • Loading branch information
WafaaNasr authored Nov 8, 2023
2 parents ba832da + d95426a commit 4ba5337
Show file tree
Hide file tree
Showing 19 changed files with 336 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

set -euo pipefail

ts-node .buildkite/scripts/pipelines/security_solution_quality_gate/pipeline.ts
ts-node .buildkite/scripts/pipelines/security_solution_quality_gate/security_solution_cypress/pipeline.ts
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ src/plugins/embeddable @elastic/kibana-presentation
x-pack/examples/embedded_lens_example @elastic/kibana-visualizations
x-pack/plugins/encrypted_saved_objects @elastic/kibana-security
x-pack/plugins/enterprise_search @elastic/enterprise-search-frontend
examples/error_boundary @elastic/appex-sharedux
packages/kbn-es @elastic/kibana-operations
packages/kbn-es-archiver @elastic/kibana-operations @elastic/appex-qa
packages/kbn-es-errors @elastic/kibana-core
Expand Down
3 changes: 3 additions & 0 deletions examples/error_boundary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Error Boundary Example

A very simple example plugin for testing Kibana Error Boundary.
14 changes: 14 additions & 0 deletions examples/error_boundary/kibana.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"type": "plugin",
"id": "@kbn/error-boundary-example-plugin",
"owner": "@elastic/appex-sharedux",
"description": "A plugin which exemplifes the KibanaErrorBoundary",
"plugin": {
"id": "error_boundary_example",
"server": false,
"browser": true,
"requiredPlugins": [
"developerExamples"
]
}
}
12 changes: 12 additions & 0 deletions examples/error_boundary/public/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { ErrorBoundaryExamplePlugin } from './plugin';

export function plugin() {
return new ErrorBoundaryExamplePlugin();
}
111 changes: 111 additions & 0 deletions examples/error_boundary/public/plugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { EuiButton } from '@elastic/eui';

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
import { KibanaErrorBoundary, KibanaErrorBoundaryProvider } from '@kbn/shared-ux-error-boundary';
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';

interface SetupDeps {
developerExamples: DeveloperExamplesSetup;
}

const useErrors = () => {
return useState(false);
};

export const FatalComponent = () => {
const [hasError, setHasError] = useErrors();

if (hasError) {
const fatalError = new Error('Example of unknown error type');
throw fatalError;
}

return (
<EuiButton
onClick={() => {
setHasError(true);
}}
data-test-subj="fatalErrorBtn"
>
Click for fatal error
</EuiButton>
);
};

export const RecoverableComponent = () => {
const [hasError, setHasError] = useErrors();

if (hasError) {
// FIXME: use network interception to disable responses
// for chunk requests and attempt to lazy-load a component
// https://github.com/elastic/kibana/issues/170777
const upgradeError = new Error('ChunkLoadError');
upgradeError.name = 'ChunkLoadError';
throw upgradeError;
}

return (
<EuiButton
onClick={() => {
setHasError(true);
}}
data-test-subj="recoverableErrorBtn"
>
Click for recoverable error
</EuiButton>
);
};

export class ErrorBoundaryExamplePlugin implements Plugin<void, void, SetupDeps> {
public setup(core: CoreSetup, deps: SetupDeps) {
// Register an application into the side navigation menu
core.application.register({
id: 'errorBoundaryExample',
title: 'Error Boundary Example',
async mount({ element }: AppMountParameters) {
ReactDOM.render(
<KibanaErrorBoundaryProvider analytics={core.analytics}>
<KibanaErrorBoundary>
<KibanaPageTemplate>
<KibanaPageTemplate.Header
pageTitle="KibanaErrorBoundary example"
data-test-subj="errorBoundaryExampleHeader"
/>
<KibanaPageTemplate.Section grow={false}>
<FatalComponent />
</KibanaPageTemplate.Section>
<KibanaPageTemplate.Section>
<RecoverableComponent />
</KibanaPageTemplate.Section>
</KibanaPageTemplate>
</KibanaErrorBoundary>
</KibanaErrorBoundaryProvider>,
element
);
return () => ReactDOM.unmountComponentAtNode(element);
},
});

// This section is only needed to get this example plugin to show up in our Developer Examples.
deps.developerExamples.register({
appId: 'errorBoundaryExample',
title: 'Error Boundary Example Application',
description: `Build a plugin that registers an application that simply says "Error Boundary Example"`,
});
}
public start(_core: CoreStart) {
return {};
}
public stop() {}
}
22 changes: 22 additions & 0 deletions examples/error_boundary/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "target/types"
},
"include": [
"index.ts",
"common/**/*.ts",
"public/**/*.ts",
"public/**/*.tsx",
"../../typings/**/*"
],
"exclude": [
"target/**/*"
],
"kbn_references": [
"@kbn/core",
"@kbn/developer-examples-plugin",
"@kbn/shared-ux-error-boundary",
"@kbn/shared-ux-page-kibana-template"
]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@
"@kbn/embedded-lens-example-plugin": "link:x-pack/examples/embedded_lens_example",
"@kbn/encrypted-saved-objects-plugin": "link:x-pack/plugins/encrypted_saved_objects",
"@kbn/enterprise-search-plugin": "link:x-pack/plugins/enterprise_search",
"@kbn/error-boundary-example-plugin": "link:examples/error_boundary",
"@kbn/es-errors": "link:packages/kbn-es-errors",
"@kbn/es-query": "link:packages/kbn-es-query",
"@kbn/es-types": "link:packages/kbn-es-types",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('<KibanaErrorBoundary>', () => {
expect(await findByText(strings.recoverable.callout.title())).toBeVisible();
expect(await findByText(strings.recoverable.callout.pageReloadButton())).toBeVisible();

(await findByTestId('recoverablePromptReloadBtn')).click();
(await findByTestId('errorBoundaryRecoverablePromptReloadBtn')).click();

expect(reloadSpy).toHaveBeenCalledTimes(1);
});
Expand All @@ -69,7 +69,7 @@ describe('<KibanaErrorBoundary>', () => {
expect(await findByText(strings.fatal.callout.showDetailsButton())).toBeVisible();
expect(await findByText(strings.fatal.callout.pageReloadButton())).toBeVisible();

(await findByTestId('fatalPromptReloadBtn')).click();
(await findByTestId('errorBoundaryFatalPromptReloadBtn')).click();

expect(reloadSpy).toHaveBeenCalledTimes(1);
});
Expand Down
30 changes: 21 additions & 9 deletions packages/shared-ux/error_boundary/src/ui/message_components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const CodePanel: React.FC<ErrorCalloutProps & { onClose: () => void }> = (props)
</EuiPanel>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiCodeBlock>
<EuiCodeBlock data-test-subj="errorBoundaryFatalDetailsErrorString">
<p>{(error.stack ?? error.toString()) + '\n\n'}</p>
<p>
{errorName}
Expand Down Expand Up @@ -93,25 +93,29 @@ export const FatalPrompt: React.FC<ErrorCalloutProps> = (props) => {

return (
<EuiEmptyPrompt
title={<h2>{strings.fatal.callout.title()}</h2>}
title={<h2 data-test-subj="errorBoundaryFatalHeader">{strings.fatal.callout.title()}</h2>}
color="danger"
iconType="error"
body={
<>
<p>{strings.fatal.callout.body()}</p>
<p data-test-subj="errorBoundaryFatalPromptBody">{strings.fatal.callout.body()}</p>
<p>
<EuiButton
color="danger"
iconType="refresh"
fill={true}
onClick={onClickRefresh}
data-test-subj="fatalPromptReloadBtn"
data-test-subj="errorBoundaryFatalPromptReloadBtn"
>
{strings.fatal.callout.pageReloadButton()}
</EuiButton>
</p>
<p>
<EuiLink color="danger" onClick={() => setIsFlyoutVisible(true)}>
<EuiLink
color="danger"
onClick={() => setIsFlyoutVisible(true)}
data-test-subj="errorBoundaryFatalShowDetailsBtn"
>
{strings.fatal.callout.showDetailsButton()}
</EuiLink>
{isFlyoutVisible ? (
Expand All @@ -128,17 +132,25 @@ export const RecoverablePrompt = (props: ErrorCalloutProps) => {
const { onClickRefresh } = props;
return (
<EuiEmptyPrompt
iconType="warning"
title={<h2>{strings.recoverable.callout.title()}</h2>}
body={<p>{strings.recoverable.callout.body()}</p>}
title={
<h2 data-test-subj="errorBoundaryRecoverableHeader">
{strings.recoverable.callout.title()}
</h2>
}
color="warning"
iconType="warning"
body={
<p data-test-subj="errorBoundaryRecoverablePromptBody">
{strings.recoverable.callout.body()}
</p>
}
actions={
<EuiButton
color="warning"
iconType="refresh"
fill={true}
onClick={onClickRefresh}
data-test-subj="recoverablePromptReloadBtn"
data-test-subj="errorBoundaryRecoverablePromptReloadBtn"
>
{strings.recoverable.callout.pageReloadButton()}
</EuiButton>
Expand Down
1 change: 1 addition & 0 deletions test/examples/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default async function ({ readConfigFile }) {
require.resolve('./content_management'),
require.resolve('./unified_field_list_examples'),
require.resolve('./discover_customization_examples'),
require.resolve('./error_boundary'),
],
services: {
...functionalConfig.get('services'),
Expand Down
68 changes: 68 additions & 0 deletions test/examples/error_boundary/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import expect from '@kbn/expect';
import { FtrProviderContext } from '../../functional/ftr_provider_context';

// eslint-disable-next-line import/no-default-export
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const retry = getService('retry');
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common']);
const log = getService('log');

describe('Error Boundary Examples', () => {
before(async () => {
await PageObjects.common.navigateToApp('errorBoundaryExample');
await testSubjects.existOrFail('errorBoundaryExampleHeader');
});

it('fatal error', async () => {
log.debug('clicking button for fatal error');
await testSubjects.click('fatalErrorBtn');
const errorHeader = await testSubjects.getVisibleText('errorBoundaryFatalHeader');
expect(errorHeader).to.not.be(undefined);

log.debug('checking that the error has taken over the page');
await testSubjects.missingOrFail('errorBoundaryExampleHeader');

await testSubjects.click('errorBoundaryFatalShowDetailsBtn');
const errorString = await testSubjects.getVisibleText('errorBoundaryFatalDetailsErrorString');
expect(errorString).to.match(/Error: Example of unknown error type/);

log.debug('closing error flyout');
await testSubjects.click('euiFlyoutCloseButton');

log.debug('clicking page refresh');
await testSubjects.click('errorBoundaryFatalPromptReloadBtn');

await retry.try(async () => {
log.debug('checking for page refresh');
await testSubjects.existOrFail('errorBoundaryExampleHeader');
});
});

it('recoverable error', async () => {
log.debug('clicking button for recoverable error');
await testSubjects.click('recoverableErrorBtn');
const errorHeader = await testSubjects.getVisibleText('errorBoundaryRecoverableHeader');
expect(errorHeader).to.not.be(undefined);

log.debug('checking that the error has taken over the page');
await testSubjects.missingOrFail('errorBoundaryExampleHeader');

log.debug('clicking page refresh');
await testSubjects.click('errorBoundaryRecoverablePromptReloadBtn');

await retry.try(async () => {
log.debug('checking for page refresh');
await testSubjects.existOrFail('errorBoundaryExampleHeader');
});
});
});
}
8 changes: 5 additions & 3 deletions test/functional/apps/visualize/group3/_annotation_listing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const retry = getService('retry');
const log = getService('log');

// Failing: See https://github.com/elastic/kibana/issues/170578
describe.skip('annotation listing page', function () {
describe('annotation listing page', function () {
before(async function () {
await kibanaServer.importExport.load(
'test/functional/fixtures/kbn_archiver/annotation_listing_page_search'
Expand Down Expand Up @@ -156,11 +155,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});

await PageObjects.annotationEditor.saveGroup();
await listingTable.clearSearchFilter();
});
});

describe('data view switching', () => {
before(async () => {
await listingTable.clearSearchFilter();
});

it('recovers from missing data view', async () => {
await listingTable.clickItemLink('eventAnnotation', 'missing data view');

Expand Down
2 changes: 2 additions & 0 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,8 @@
"@kbn/encrypted-saved-objects-plugin/*": ["x-pack/plugins/encrypted_saved_objects/*"],
"@kbn/enterprise-search-plugin": ["x-pack/plugins/enterprise_search"],
"@kbn/enterprise-search-plugin/*": ["x-pack/plugins/enterprise_search/*"],
"@kbn/error-boundary-example-plugin": ["examples/error_boundary"],
"@kbn/error-boundary-example-plugin/*": ["examples/error_boundary/*"],
"@kbn/es": ["packages/kbn-es"],
"@kbn/es/*": ["packages/kbn-es/*"],
"@kbn/es-archiver": ["packages/kbn-es-archiver"],
Expand Down
Loading

0 comments on commit 4ba5337

Please sign in to comment.