diff --git a/.eslintrc.js b/.eslintrc.js
index e2674e8d7b407..c9f9d96f9ddae 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -771,19 +771,22 @@ module.exports = {
},
/**
- * APM overrides
+ * APM and Observability overrides
*/
{
- files: ['x-pack/plugins/apm/**/*.js'],
+ files: [
+ 'x-pack/plugins/apm/**/*.{js,mjs,ts,tsx}',
+ 'x-pack/plugins/observability/**/*.{js,mjs,ts,tsx}',
+ ],
rules: {
- 'no-unused-vars': ['error', { ignoreRestSiblings: true }],
'no-console': ['warn', { allow: ['error'] }],
- },
- },
- {
- plugins: ['react-hooks'],
- files: ['x-pack/plugins/apm/**/*.{ts,tsx}'],
- rules: {
+ 'react/function-component-definition': [
+ 'warn',
+ {
+ namedComponents: 'function-declaration',
+ unnamedComponents: 'arrow-function',
+ },
+ ],
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
'react-hooks/exhaustive-deps': ['error', { additionalHooks: '^useFetcher$' }],
},
diff --git a/docs/developer/architecture/code-exploration.asciidoc b/docs/developer/architecture/code-exploration.asciidoc
index f18a6c2f14926..4481dea44795c 100644
--- a/docs/developer/architecture/code-exploration.asciidoc
+++ b/docs/developer/architecture/code-exploration.asciidoc
@@ -524,9 +524,9 @@ WARNING: Missing README.
See Configuring security in Kibana.
-- {kib-repo}blob/{branch}/x-pack/plugins/security_solution[securitySolution]
+- {kib-repo}blob/{branch}/x-pack/plugins/security_solution/README.md[securitySolution]
-WARNING: Missing README.
+Welcome to the Kibana Security Solution plugin! This README will go over getting started with development and testing.
- {kib-repo}blob/{branch}/x-pack/plugins/snapshot_restore/README.md[snapshotRestore]
diff --git a/docs/developer/contributing/development-tests.asciidoc b/docs/developer/contributing/development-tests.asciidoc
index 78a2a90b69ce5..2e40f664faba9 100644
--- a/docs/developer/contributing/development-tests.asciidoc
+++ b/docs/developer/contributing/development-tests.asciidoc
@@ -26,8 +26,6 @@ root)
|Functional
|`test/*integration/**/config.js` `test/*functional/**/config.js` `test/accessibility/config.js`
|`yarn test:ftr:server --config test/[directory]/config.js``yarn test:ftr:runner --config test/[directory]/config.js --grep=regexp`
-
-|Karma |`src/**/public/__tests__/*.js` |`yarn test:karma:debug`
|===
For X-Pack tests located in `x-pack/` see
diff --git a/docs/developer/contributing/development-unit-tests.asciidoc b/docs/developer/contributing/development-unit-tests.asciidoc
index 8b4954150bb5b..5322106b17ac1 100644
--- a/docs/developer/contributing/development-unit-tests.asciidoc
+++ b/docs/developer/contributing/development-unit-tests.asciidoc
@@ -95,38 +95,6 @@ to proceed in this mode.
node scripts/mocha --debug
----
-With `yarn test:karma`, you can run only the browser tests. Coverage
-reports are available for browser tests by running
-`yarn test:coverage`. You can find the results under the `coverage/`
-directory that will be created upon completion.
-
-[source,bash]
-----
-yarn test:karma
-----
-
-Using `yarn test:karma:debug` initializes an environment for debugging
-the browser tests. Includes an dedicated instance of the {kib} server
-for building the test bundle, and a karma server. When running this task
-the build is optimized for the first time and then a karma-owned
-instance of the browser is opened. Click the "`debug`" button to open a
-new tab that executes the unit tests.
-
-[source,bash]
-----
-yarn test:karma:debug
-----
-
-In the screenshot below, you’ll notice the URL is
-`localhost:9876/debug.html`. You can append a `grep` query parameter
-to this URL and set it to a string value which will be used to exclude
-tests which don’t match. For example, if you changed the URL to
-`localhost:9876/debug.html?query=my test` and then refreshed the
-browser, you’d only see tests run which contain "`my test`" in the test
-description.
-
-image:http://i.imgur.com/DwHxgfq.png[Browser test debugging]
-
[discrete]
=== Unit Testing Plugins
@@ -141,5 +109,4 @@ command from your plugin:
[source,bash]
----
yarn test:mocha
-yarn test:karma:debug # remove the debug flag to run them once and close
----
\ No newline at end of file
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md
index 37142cf1794c3..bc34d4113f847 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md
@@ -52,5 +52,6 @@ esFilters: {
convertRangeFilterToTimeRangeString: typeof convertRangeFilterToTimeRangeString;
mapAndFlattenFilters: (filters: import("../common").Filter[]) => import("../common").Filter[];
extractTimeFilter: typeof extractTimeFilter;
+ extractTimeRange: typeof extractTimeRange;
}
```
diff --git a/package.json b/package.json
index 594f0ce583987..0c49ec26be194 100644
--- a/package.json
+++ b/package.json
@@ -41,8 +41,6 @@
"kbn": "node scripts/kbn",
"es": "node scripts/es",
"test": "grunt test",
- "test:karma": "grunt test:karma",
- "test:karma:debug": "grunt test:karmaDebug",
"test:jest": "node scripts/jest",
"test:jest_integration": "node scripts/jest_integration",
"test:mocha": "node scripts/mocha",
@@ -435,7 +433,7 @@
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-prefer-object-spread": "^1.2.1",
"eslint-plugin-prettier": "^3.1.3",
- "eslint-plugin-react": "^7.17.0",
+ "eslint-plugin-react": "^7.20.3",
"eslint-plugin-react-hooks": "^4.0.4",
"eslint-plugin-react-perf": "^3.2.3",
"exit-hook": "^2.2.0",
@@ -447,7 +445,6 @@
"grunt-available-tasks": "^0.6.3",
"grunt-cli": "^1.2.0",
"grunt-contrib-watch": "^1.1.0",
- "grunt-karma": "^3.0.2",
"grunt-peg": "^2.0.1",
"grunt-run": "0.8.1",
"gulp-babel": "^8.0.0",
@@ -465,14 +462,6 @@
"jest-raw-loader": "^1.0.1",
"jimp": "^0.9.6",
"json5": "^1.0.1",
- "karma": "5.0.2",
- "karma-chrome-launcher": "2.2.0",
- "karma-coverage": "1.1.2",
- "karma-firefox-launcher": "1.1.0",
- "karma-ie-launcher": "1.0.0",
- "karma-junit-reporter": "1.2.0",
- "karma-mocha": "2.0.0",
- "karma-safari-launcher": "1.0.0",
"license-checker": "^16.0.0",
"listr": "^0.14.1",
"load-grunt-config": "^3.0.1",
diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js
index 6cb2f3d2901d3..baf5baaf916aa 100755
--- a/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js
+++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js
@@ -28,13 +28,9 @@ exports.getWebpackConfig = function (kibanaPath, projectRoot, config) {
const alias = {
// Kibana defaults https://github.com/elastic/kibana/blob/6998f074542e8c7b32955db159d15661aca253d7/src/legacy/ui/ui_bundler_env.js#L30-L36
ui: fromKibana('src/legacy/ui/public'),
- test_harness: fromKibana('src/test_harness/public'),
// Dev defaults for test bundle https://github.com/elastic/kibana/blob/6998f074542e8c7b32955db159d15661aca253d7/src/core_plugins/tests_bundle/index.js#L73-L78
ng_mock$: fromKibana('src/test_utils/public/ng_mock'),
- 'angular-mocks$': fromKibana(
- 'src/legacy/core_plugins/tests_bundle/webpackShims/angular-mocks.js'
- ),
fixtures: fromKibana('src/fixtures'),
test_utils: fromKibana('src/test_utils/public'),
};
diff --git a/packages/kbn-plugin-generator/README.md b/packages/kbn-plugin-generator/README.md
index 95de0e93fd075..6ad665f9b87f8 100644
--- a/packages/kbn-plugin-generator/README.md
+++ b/packages/kbn-plugin-generator/README.md
@@ -71,10 +71,6 @@ Generated plugins receive a handful of scripts that can be used during developme
Build a distributable archive of your plugin.
- - `yarn test:karma`
-
- Run the browser tests in a real web browser.
-
- `yarn test:mocha`
Run the server tests using mocha.
diff --git a/packages/kbn-plugin-helpers/README.md b/packages/kbn-plugin-helpers/README.md
index 4c648fd9bde8c..d7ed3106c1ceb 100644
--- a/packages/kbn-plugin-helpers/README.md
+++ b/packages/kbn-plugin-helpers/README.md
@@ -30,7 +30,6 @@ $ plugin-helpers help
start Start kibana and have it include this plugin
build [options] [files...] Build a distributable archive
test Run the server and browser tests
- test:karma [options] Run the browser tests in a real web browser
test:mocha [files...] Run the server tests using mocha
Options:
diff --git a/packages/kbn-plugin-helpers/src/cli.ts b/packages/kbn-plugin-helpers/src/cli.ts
index b894f854a484f..18ddc62cba8a6 100644
--- a/packages/kbn-plugin-helpers/src/cli.ts
+++ b/packages/kbn-plugin-helpers/src/cli.ts
@@ -62,25 +62,6 @@ program
}))
);
-program
- .command('test')
- .description('Run the server and browser tests')
- .on('--help', docs('test/all'))
- .action(createCommanderAction('testAll'));
-
-program
- .command('test:karma')
- .description('Run the browser tests in a real web browser')
- .option('--dev', 'Enable dev mode, keeps the test server running')
- .option('-p, --plugins ', "Manually specify which plugins' test bundles to run")
- .on('--help', docs('test/karma'))
- .action(
- createCommanderAction('testKarma', (command) => ({
- dev: Boolean(command.dev),
- plugins: command.plugins,
- }))
- );
-
program
.command('test:mocha [files...]')
.description('Run the server tests using mocha')
diff --git a/packages/kbn-plugin-helpers/src/lib/tasks.ts b/packages/kbn-plugin-helpers/src/lib/tasks.ts
index 7817838760a2e..bd86bb670ff39 100644
--- a/packages/kbn-plugin-helpers/src/lib/tasks.ts
+++ b/packages/kbn-plugin-helpers/src/lib/tasks.ts
@@ -19,23 +19,17 @@
import { buildTask } from '../tasks/build';
import { startTask } from '../tasks/start';
-import { testAllTask } from '../tasks/test/all';
-import { testKarmaTask } from '../tasks/test/karma';
import { testMochaTask } from '../tasks/test/mocha';
// define a tasks interface that we can extend in the tests
export interface Tasks {
build: typeof buildTask;
start: typeof startTask;
- testAll: typeof testAllTask;
- testKarma: typeof testKarmaTask;
testMocha: typeof testMochaTask;
}
export const tasks: Tasks = {
build: buildTask,
start: startTask,
- testAll: testAllTask,
- testKarma: testKarmaTask,
testMocha: testMochaTask,
};
diff --git a/packages/kbn-plugin-helpers/src/tasks/test/all/README.md b/packages/kbn-plugin-helpers/src/tasks/test/all/README.md
deleted file mode 100644
index 4f5a72ac0d523..0000000000000
--- a/packages/kbn-plugin-helpers/src/tasks/test/all/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-Runs both the mocha and karma tests, in that order.
-
-This is just a simple caller to both `test/mocha` and `test/karma`
\ No newline at end of file
diff --git a/packages/kbn-plugin-helpers/src/tasks/test/all/index.ts b/packages/kbn-plugin-helpers/src/tasks/test/all/index.ts
deleted file mode 100644
index be8db50825fc9..0000000000000
--- a/packages/kbn-plugin-helpers/src/tasks/test/all/index.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export * from './test_all_task';
diff --git a/packages/kbn-plugin-helpers/src/tasks/test/karma/README.md b/packages/kbn-plugin-helpers/src/tasks/test/karma/README.md
deleted file mode 100644
index 8d921e8312344..0000000000000
--- a/packages/kbn-plugin-helpers/src/tasks/test/karma/README.md
+++ /dev/null
@@ -1,60 +0,0 @@
-writing tests
-=============
-
-Browser tests are written just like server tests, they are just executed differently.
-
- - place tests near the code they test, in `__tests__` directories throughout
- the public directory
-
- - Use the same bdd-style `describe()` and `it()`
- api to define the suites and cases of your tests.
-
- ```js
- describe('some portion of your code', function () {
- it('should do this thing', function () {
- expect(true).to.be(false);
- });
- });
- ```
-
-
-starting the test runner
-========================
-
-Under the covers this command uses the `test:karma` task from kibana. This will execute
-your tasks once and exit when complete.
-
-When run with the `--dev` option, the command uses the `test:karma:debug` task from kibana.
-This task sets-up a test runner that will watch your code for changes and rebuild your
-tests when necessary. You access the test runner through a browser that it starts itself
-(via Karma).
-
-If your plugin consists of a number of internal plugins, you may wish to keep the tests
-isolated to a specific plugin or plugins, instead of executing all of the tests. To do this,
-use `--plugins` and passing the plugins you would like to test. Multiple plugins can be
-specified by separating them with commas.
-
-
-running the tests
-=================
-
-Once the test runner has started you a new browser window should be opened and you should
-see a message saying "connected". Next to that is a "DEBUG" button. This button will open
-an interactive version of your tests that you can refresh, inspects, and otherwise debug
-while you write your tests.
-
-
-focus on the task at hand
-=========================
-
-To limit the tests that run you can either:
-
- 1. use the ?grep= query string to filter the test cases/suites by name
- 2. Click the suite title or (play) button next to test output
- 3. Add `.only` to your `describe()` or `it()` calls:
-
- ```js
- describe.only('suite name', function () {
- // ...
- });
- ```
diff --git a/packages/kbn-plugin-helpers/src/tasks/test/karma/index.ts b/packages/kbn-plugin-helpers/src/tasks/test/karma/index.ts
deleted file mode 100644
index 3089357b49991..0000000000000
--- a/packages/kbn-plugin-helpers/src/tasks/test/karma/index.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export * from './test_karma_task';
diff --git a/packages/kbn-plugin-helpers/src/tasks/test/karma/test_karma_task.ts b/packages/kbn-plugin-helpers/src/tasks/test/karma/test_karma_task.ts
deleted file mode 100644
index 2fe8134209894..0000000000000
--- a/packages/kbn-plugin-helpers/src/tasks/test/karma/test_karma_task.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { execFileSync } from 'child_process';
-
-import { TaskContext } from '../../../lib';
-import { winCmd } from '../../../lib/win_cmd';
-
-export function testKarmaTask({ plugin, options }: TaskContext) {
- options = options || {};
-
- const kbnServerArgs = ['--kbnServer.plugin-path=' + plugin.root];
-
- if (options.plugins) {
- kbnServerArgs.push('--kbnServer.tests_bundle.pluginId=' + options.plugins);
- } else {
- kbnServerArgs.push('--kbnServer.tests_bundle.pluginId=' + plugin.id);
- }
-
- const task = options.dev ? 'test:karma:debug' : 'test:karma';
- const args = [task].concat(kbnServerArgs);
- execFileSync(winCmd('yarn'), args, {
- cwd: plugin.kibanaRoot,
- stdio: ['ignore', 1, 2],
- });
-}
diff --git a/packages/kbn-test/src/failed_tests_reporter/__fixtures__/index.ts b/packages/kbn-test/src/failed_tests_reporter/__fixtures__/index.ts
index 16ebe10ad5426..11d6cb6a2b47b 100644
--- a/packages/kbn-test/src/failed_tests_reporter/__fixtures__/index.ts
+++ b/packages/kbn-test/src/failed_tests_reporter/__fixtures__/index.ts
@@ -21,6 +21,5 @@ const Fs = jest.requireActual('fs');
export const FTR_REPORT = Fs.readFileSync(require.resolve('./ftr_report.xml'), 'utf8');
export const JEST_REPORT = Fs.readFileSync(require.resolve('./jest_report.xml'), 'utf8');
-export const KARMA_REPORT = Fs.readFileSync(require.resolve('./karma_report.xml'), 'utf8');
export const MOCHA_REPORT = Fs.readFileSync(require.resolve('./mocha_report.xml'), 'utf8');
export const CYPRESS_REPORT = Fs.readFileSync(require.resolve('./cypress_report.xml'), 'utf8');
diff --git a/packages/kbn-test/src/failed_tests_reporter/__fixtures__/karma_report.xml b/packages/kbn-test/src/failed_tests_reporter/__fixtures__/karma_report.xml
deleted file mode 100644
index 5c4bdb9f50adf..0000000000000
--- a/packages/kbn-test/src/failed_tests_reporter/__fixtures__/karma_report.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Error: expected 7069 to be below 64
- at Assertion.__kbnBundles__.tests../packages/kbn-expect/expect.js.Assertion.assert (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:13671:11)
- at Assertion.__kbnBundles__.tests../packages/kbn-expect/expect.js.Assertion.lessThan.Assertion.below (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:13891:8)
- at Function.lessThan (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:14078:15)
- at _callee3$ (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158985:60)
- at tryCatch (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:62:40)
- at Generator.invoke [as _invoke] (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:288:22)
- at Generator.prototype.<computed> [as next] (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:114:21)
- at asyncGeneratorStep (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158772:103)
- at _next (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158774:194)
-
-
-
-
-
-
-
-
-
diff --git a/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts b/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts
index 53a74f6cc6af2..505e898c62adf 100644
--- a/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts
+++ b/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts
@@ -39,13 +39,7 @@ jest.mock('fs', () => {
};
});
-import {
- FTR_REPORT,
- JEST_REPORT,
- MOCHA_REPORT,
- KARMA_REPORT,
- CYPRESS_REPORT,
-} from './__fixtures__';
+import { FTR_REPORT, JEST_REPORT, MOCHA_REPORT, CYPRESS_REPORT } from './__fixtures__';
import { parseTestReport } from './test_report';
import { addMessagesToReport } from './add_messages_to_report';
@@ -338,79 +332,3 @@ it('rewrites cypress reports with minimal changes', async () => {
`);
});
-
-it('rewrites karma reports with minimal changes', async () => {
- const xml = await addMessagesToReport({
- report: await parseTestReport(KARMA_REPORT),
- messages: [
- {
- name:
- 'CoordinateMapsVisualizationTest CoordinateMapsVisualization - basics should initialize OK',
- classname: 'Browser Unit Tests.CoordinateMapsVisualizationTest',
- message: 'foo bar',
- },
- ],
- log,
- reportPath: Path.resolve(__dirname, './__fixtures__/karma_report.xml'),
- });
-
- expect(createPatch('karma.xml', KARMA_REPORT, xml, { context: 0 })).toMatchInlineSnapshot(`
- Index: karma.xml
- ===================================================================
- --- karma.xml [object Object]
- +++ karma.xml
- @@ -1,5 +1,5 @@
- -‹?xml version="1.0"?›
- +‹?xml version="1.0" encoding="utf-8"?›
- ‹testsuite name="Chrome 75.0.3770 (Mac OS X 10.14.5)" package="" timestamp="2019-07-02T19:53:21" id="0" hostname="spalger.lan" tests="648" errors="0" failures="4" time="1.759"›
- ‹properties›
- ‹property name="browser.fullName" value="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"/›
- ‹/properties›
- @@ -7,27 +7,31 @@
- ‹testcase name="Vis-Editor-Agg-Params plugin directive should hide custom label parameter" time="0" classname="Browser Unit Tests.Vis-Editor-Agg-Params plugin directive"›
- ‹skipped/›
- ‹/testcase›
- ‹testcase name="CoordinateMapsVisualizationTest CoordinateMapsVisualization - basics should initialize OK" time="0.265" classname="Browser Unit Tests.CoordinateMapsVisualizationTest"›
- - ‹failure type=""›Error: expected 7069 to be below 64
- - at Assertion.__kbnBundles__.tests../packages/kbn-expect/expect.js.Assertion.assert (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:13671:11)
- - at Assertion.__kbnBundles__.tests../packages/kbn-expect/expect.js.Assertion.lessThan.Assertion.below (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:13891:8)
- - at Function.lessThan (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:14078:15)
- - at _callee3$ (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158985:60)
- + ‹failure type=""›‹![CDATA[Error: expected 7069 to be below 64
- + at Assertion.__kbnBundles__.tests../packages/kbn-expect/expect.js.Assertion.assert (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:13671:11)
- + at Assertion.__kbnBundles__.tests../packages/kbn-expect/expect.js.Assertion.lessThan.Assertion.below (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:13891:8)
- + at Function.lessThan (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:14078:15)
- + at _callee3$ (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158985:60)
- at tryCatch (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:62:40)
- at Generator.invoke [as _invoke] (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:288:22)
- - at Generator.prototype.<computed> [as next] (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:114:21)
- - at asyncGeneratorStep (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158772:103)
- - at _next (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158774:194)
- -‹/failure›
- + at Generator.prototype.‹computed› [as next] (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:114:21)
- + at asyncGeneratorStep (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158772:103)
- + at _next (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158774:194)
- +]]›‹/failure›
- + ‹system-out›Failed Tests Reporter:
- + - foo bar
- +
- +‹/system-out›
- ‹/testcase›
- ‹testcase name="CoordinateMapsVisualizationTest CoordinateMapsVisualization - basics should toggle to Heatmap OK" time="0.055" classname="Browser Unit Tests.CoordinateMapsVisualizationTest"/›
- ‹testcase name="VegaParser._parseSchema should warn on vega-lite version too new to be supported" time="0.001" classname="Browser Unit Tests.VegaParser·_parseSchema"/›
- ‹system-out›
- - ‹![CDATA[Chrome 75.0.3770 (Mac OS X 10.14.5) LOG: 'ready to load tests for shard 1 of 4'
- + Chrome 75.0.3770 (Mac OS X 10.14.5) LOG: 'ready to load tests for shard 1 of 4'
- ,Chrome 75.0.3770 (Mac OS X 10.14.5) WARN: 'Unmatched GET to http://localhost:9876/api/interpreter/fns'
- ...
-
- -]]›
- +
- ‹/system-out›
- ‹system-err/›
- -‹/testsuite›
- +‹/testsuite›
- \\ No newline at end of file
-
- `);
-});
diff --git a/packages/kbn-test/src/failed_tests_reporter/get_failures.test.ts b/packages/kbn-test/src/failed_tests_reporter/get_failures.test.ts
index 23d9805727f32..f570ed36111b3 100644
--- a/packages/kbn-test/src/failed_tests_reporter/get_failures.test.ts
+++ b/packages/kbn-test/src/failed_tests_reporter/get_failures.test.ts
@@ -19,7 +19,7 @@
import { getFailures } from './get_failures';
import { parseTestReport } from './test_report';
-import { FTR_REPORT, JEST_REPORT, KARMA_REPORT, MOCHA_REPORT } from './__fixtures__';
+import { FTR_REPORT, JEST_REPORT, MOCHA_REPORT } from './__fixtures__';
it('discovers failures in ftr report', async () => {
const failures = getFailures(await parseTestReport(FTR_REPORT));
@@ -85,31 +85,6 @@ it('discovers failures in jest report', async () => {
`);
});
-it('discovers failures in karma report', async () => {
- const failures = getFailures(await parseTestReport(KARMA_REPORT));
- expect(failures).toMatchInlineSnapshot(`
- Array [
- Object {
- "classname": "Browser Unit Tests.CoordinateMapsVisualizationTest",
- "failure": "Error: expected 7069 to be below 64
- at Assertion.__kbnBundles__.tests../packages/kbn-expect/expect.js.Assertion.assert (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:13671:11)
- at Assertion.__kbnBundles__.tests../packages/kbn-expect/expect.js.Assertion.lessThan.Assertion.below (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:13891:8)
- at Function.lessThan (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:14078:15)
- at _callee3$ (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158985:60)
- at tryCatch (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:62:40)
- at Generator.invoke [as _invoke] (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:288:22)
- at Generator.prototype. [as next] (webpack://%5Bname%5D/./node_modules/regenerator-runtime/runtime.js?:114:21)
- at asyncGeneratorStep (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158772:103)
- at _next (http://localhost:5610/bundles/tests.bundle.js?shards=4&shard_num=1:158774:194)
- ",
- "likelyIrrelevant": false,
- "name": "CoordinateMapsVisualizationTest CoordinateMapsVisualization - basics should initialize OK",
- "time": "0.265",
- },
- ]
- `);
-});
-
it('discovers failures in mocha report', async () => {
const failures = getFailures(await parseTestReport(MOCHA_REPORT));
expect(failures).toMatchInlineSnapshot(`
diff --git a/packages/kbn-test/src/failed_tests_reporter/report_metadata.test.ts b/packages/kbn-test/src/failed_tests_reporter/report_metadata.test.ts
index 729d80ddfcb44..c079084965609 100644
--- a/packages/kbn-test/src/failed_tests_reporter/report_metadata.test.ts
+++ b/packages/kbn-test/src/failed_tests_reporter/report_metadata.test.ts
@@ -19,7 +19,7 @@
import { getReportMessageIter } from './report_metadata';
import { parseTestReport } from './test_report';
-import { FTR_REPORT, JEST_REPORT, KARMA_REPORT, MOCHA_REPORT } from './__fixtures__';
+import { FTR_REPORT, JEST_REPORT, MOCHA_REPORT } from './__fixtures__';
it('reads messages and screenshots from metadata-json properties', async () => {
const ftrReport = await parseTestReport(FTR_REPORT);
@@ -43,7 +43,4 @@ it('reads messages and screenshots from metadata-json properties', async () => {
const mochaReport = await parseTestReport(MOCHA_REPORT);
expect(Array.from(getReportMessageIter(mochaReport))).toMatchInlineSnapshot(`Array []`);
-
- const karmaReport = await parseTestReport(KARMA_REPORT);
- expect(Array.from(getReportMessageIter(karmaReport))).toMatchInlineSnapshot(`Array []`);
});
diff --git a/packages/kbn-ui-shared-deps/theme.ts b/packages/kbn-ui-shared-deps/theme.ts
index 4b2758516fc26..a810e1de0a21f 100644
--- a/packages/kbn-ui-shared-deps/theme.ts
+++ b/packages/kbn-ui-shared-deps/theme.ts
@@ -24,7 +24,7 @@ const globals: any = typeof window === 'undefined' ? {} : window;
export type Theme = typeof LightTheme;
// in the Kibana app we can rely on this global being defined, but in
-// some cases (like jest, or karma tests) the global is undefined
+// some cases (like jest) the global is undefined
export const tag: string = globals.__kbnThemeTag__ || 'v7light';
export const version = tag.startsWith('v7') ? 7 : 8;
export const darkMode = tag.endsWith('dark');
diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md
index f7acff14915a7..72945597758e2 100644
--- a/src/core/MIGRATION.md
+++ b/src/core/MIGRATION.md
@@ -1620,14 +1620,6 @@ If others are consuming your plugin's new platform contracts via the `ui/new_pla
> Note: The `ui/new_platform` mock is only designed for use by old Jest tests. If you are writing new tests, you should structure your code and tests such that you don't need this mock. Instead, you should import the `core` mock directly and instantiate it.
-#### What about karma tests?
-
-While our plan is to only provide first-class mocks for Jest tests, there are many legacy karma tests that cannot be quickly or easily converted to Jest -- particularly those which are still relying on mocking Angular services via `ngMock`.
-
-For these tests, we are maintaining a separate set of mocks. Files with a `.karma_mock.{js|ts|tsx}` extension will be loaded _globally_ before karma tests are run.
-
-It is important to note that this behavior is different from `jest.mock('ui/new_platform')`, which only mocks tests on an individual basis. If you encounter any failures in karma tests as a result of new platform migration efforts, you may need to add a `.karma_mock.js` file for the affected services, or add to the existing karma mock we are maintaining in `ui/new_platform`.
-
### Provide Legacy Platform API to the New platform plugin
#### On the server side
diff --git a/src/core/public/legacy/legacy_service.ts b/src/core/public/legacy/legacy_service.ts
index d77676b350f93..78a9219f3d694 100644
--- a/src/core/public/legacy/legacy_service.ts
+++ b/src/core/public/legacy/legacy_service.ts
@@ -53,7 +53,7 @@ interface BootstrapModule {
* The LegacyPlatformService is responsible for initializing
* the legacy platform by injecting parts of the new platform
* services into the legacy platform modules, like ui/modules,
- * and then bootstrapping the ui/chrome or ui/test_harness to
+ * and then bootstrapping the ui/chrome or ~~ui/test_harness~~ to
* setup either the app or browser tests.
*/
export class LegacyPlatformService {
diff --git a/src/core/server/http/http_config.ts b/src/core/server/http/http_config.ts
index 83a2e712b424f..e74f6d32e92b0 100644
--- a/src/core/server/http/http_config.ts
+++ b/src/core/server/http/http_config.ts
@@ -42,21 +42,7 @@ export const config = {
validate: match(validBasePathRegex, "must start with a slash, don't end with one"),
})
),
- cors: schema.conditional(
- schema.contextRef('dev'),
- true,
- schema.object(
- {
- origin: schema.arrayOf(schema.string()),
- },
- {
- defaultValue: {
- origin: ['*://localhost:9876'], // karma test server
- },
- }
- ),
- schema.boolean({ defaultValue: false })
- ),
+ cors: schema.boolean({ defaultValue: false }),
customResponseHeaders: schema.recordOf(schema.string(), schema.any(), {
defaultValue: {},
}),
diff --git a/src/dev/build/tasks/copy_source_task.ts b/src/dev/build/tasks/copy_source_task.ts
index 221c9162bd2a9..c8489673b83af 100644
--- a/src/dev/build/tasks/copy_source_task.ts
+++ b/src/dev/build/tasks/copy_source_task.ts
@@ -33,7 +33,6 @@ export const CopySource: Task = {
'!src/**/{__tests__,__snapshots__,__mocks__}/**',
'!src/test_utils/**',
'!src/fixtures/**',
- '!src/legacy/core_plugins/tests_bundle/**',
'!src/legacy/core_plugins/console/public/tests/**',
'!src/cli/cluster/**',
'!src/cli/repl/**',
diff --git a/src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.js b/src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.ts
similarity index 80%
rename from src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.js
rename to src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.ts
index 3f34a84057668..7a8f7316913be 100644
--- a/src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.js
+++ b/src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.ts
@@ -18,10 +18,14 @@
*/
import { resolve } from 'path';
-import { compressTar, copyAll, mkdirp, write } from '../../../lib';
+
+import { ToolingLog } from '@kbn/dev-utils';
+
+import { compressTar, copyAll, mkdirp, write, Config } from '../../../lib';
import { dockerfileTemplate } from './templates';
+import { TemplateContext } from './template_context';
-export async function bundleDockerFiles(config, log, build, scope) {
+export async function bundleDockerFiles(config: Config, log: ToolingLog, scope: TemplateContext) {
log.info(
`Generating kibana${scope.imageFlavor}${scope.ubiImageFlavor} docker build context bundle`
);
@@ -50,17 +54,15 @@ export async function bundleDockerFiles(config, log, build, scope) {
// Compress dockerfiles dir created inside
// docker build dir as output it as a target
// on targets folder
- await compressTar(
- {
- archiverOptions: {
- gzip: true,
- gzipOptions: {
- level: 9,
- },
+ await compressTar({
+ source: dockerFilesBuildDir,
+ destination: dockerFilesOutputDir,
+ archiverOptions: {
+ gzip: true,
+ gzipOptions: {
+ level: 9,
},
- createRootDirectory: false,
},
- dockerFilesBuildDir,
- dockerFilesOutputDir
- );
+ createRootDirectory: false,
+ });
}
diff --git a/src/dev/build/tasks/os_packages/docker_generator/index.ts b/src/dev/build/tasks/os_packages/docker_generator/index.ts
index 78d2b197dc7b2..dff56585fc704 100644
--- a/src/dev/build/tasks/os_packages/docker_generator/index.ts
+++ b/src/dev/build/tasks/os_packages/docker_generator/index.ts
@@ -17,5 +17,4 @@
* under the License.
*/
-// @ts-expect-error not ts yet
export { runDockerGenerator, runDockerGeneratorForUBI } from './run';
diff --git a/src/dev/build/tasks/os_packages/docker_generator/run.js b/src/dev/build/tasks/os_packages/docker_generator/run.ts
similarity index 90%
rename from src/dev/build/tasks/os_packages/docker_generator/run.js
rename to src/dev/build/tasks/os_packages/docker_generator/run.ts
index b6dab43887f14..0a26729f3502d 100644
--- a/src/dev/build/tasks/os_packages/docker_generator/run.js
+++ b/src/dev/build/tasks/os_packages/docker_generator/run.ts
@@ -20,8 +20,12 @@
import { access, link, unlink, chmod } from 'fs';
import { resolve } from 'path';
import { promisify } from 'util';
-import { write, copyAll, mkdirp, exec } from '../../../lib';
+
+import { ToolingLog } from '@kbn/dev-utils';
+
+import { write, copyAll, mkdirp, exec, Config, Build } from '../../../lib';
import * as dockerTemplates from './templates';
+import { TemplateContext } from './template_context';
import { bundleDockerFiles } from './bundle_dockerfiles';
const accessAsync = promisify(access);
@@ -29,7 +33,12 @@ const linkAsync = promisify(link);
const unlinkAsync = promisify(unlink);
const chmodAsync = promisify(chmod);
-export async function runDockerGenerator(config, log, build, ubi = false) {
+export async function runDockerGenerator(
+ config: Config,
+ log: ToolingLog,
+ build: Build,
+ ubi: boolean = false
+) {
// UBI var config
const baseOSImage = ubi ? 'registry.access.redhat.com/ubi7/ubi-minimal:7.7' : 'centos:7';
const ubiVersionTag = 'ubi7';
@@ -52,7 +61,7 @@ export async function runDockerGenerator(config, log, build, ubi = false) {
const dockerOutputDir = config.resolveFromTarget(
`kibana${imageFlavor}${ubiImageFlavor}-${versionTag}-docker.tar.gz`
);
- const scope = {
+ const scope: TemplateContext = {
artifactTarball,
imageFlavor,
versionTag,
@@ -112,10 +121,10 @@ export async function runDockerGenerator(config, log, build, ubi = false) {
});
// Pack Dockerfiles and create a target for them
- await bundleDockerFiles(config, log, build, scope);
+ await bundleDockerFiles(config, log, scope);
}
-export async function runDockerGeneratorForUBI(config, log, build) {
+export async function runDockerGeneratorForUBI(config: Config, log: ToolingLog, build: Build) {
// Only run ubi docker image build for default distribution
if (build.isOss()) {
return;
diff --git a/packages/kbn-plugin-helpers/src/tasks/test/all/test_all_task.ts b/src/dev/build/tasks/os_packages/docker_generator/template_context.ts
similarity index 70%
rename from packages/kbn-plugin-helpers/src/tasks/test/all/test_all_task.ts
rename to src/dev/build/tasks/os_packages/docker_generator/template_context.ts
index d07c19291d2cb..115d4c6927c30 100644
--- a/packages/kbn-plugin-helpers/src/tasks/test/all/test_all_task.ts
+++ b/src/dev/build/tasks/os_packages/docker_generator/template_context.ts
@@ -17,9 +17,17 @@
* under the License.
*/
-import { TaskContext } from '../../../lib';
-
-export function testAllTask({ run }: TaskContext) {
- run('testMocha');
- run('testKarma');
+export interface TemplateContext {
+ artifactTarball: string;
+ imageFlavor: string;
+ versionTag: string;
+ license: string;
+ artifactsDir: string;
+ imageTag: string;
+ dockerBuildDir: string;
+ dockerOutputDir: string;
+ baseOSImage: string;
+ ubiImageFlavor: string;
+ dockerBuildDate: string;
+ usePublicArtifact?: boolean;
}
diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.js b/src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.ts
similarity index 94%
rename from src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.js
rename to src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.ts
index 4e8dfe188b867..ff6fcf7548d9d 100644
--- a/src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.js
+++ b/src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.ts
@@ -19,6 +19,8 @@
import dedent from 'dedent';
+import { TemplateContext } from '../template_context';
+
function generator({
imageTag,
imageFlavor,
@@ -26,7 +28,7 @@ function generator({
dockerOutputDir,
baseOSImage,
ubiImageFlavor,
-}) {
+}: TemplateContext) {
return dedent(`
#!/usr/bin/env bash
#
diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.js b/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts
similarity index 98%
rename from src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.js
rename to src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts
index 5832d00162b20..ea2f881768c8f 100755
--- a/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.js
+++ b/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts
@@ -19,6 +19,8 @@
import dedent from 'dedent';
+import { TemplateContext } from '../template_context';
+
function generator({
artifactTarball,
versionTag,
@@ -27,7 +29,7 @@ function generator({
baseOSImage,
ubiImageFlavor,
dockerBuildDate,
-}) {
+}: TemplateContext) {
const copyArtifactTarballInsideDockerOptFolder = () => {
if (usePublicArtifact) {
return `RUN cd /opt && curl --retry 8 -s -L -O https://artifacts.elastic.co/downloads/kibana/${artifactTarball} && cd -`;
diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/index.js b/src/dev/build/tasks/os_packages/docker_generator/templates/index.ts
similarity index 100%
rename from src/dev/build/tasks/os_packages/docker_generator/templates/index.js
rename to src/dev/build/tasks/os_packages/docker_generator/templates/index.ts
diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/kibana_yml.template.js b/src/dev/build/tasks/os_packages/docker_generator/templates/kibana_yml.template.ts
similarity index 91%
rename from src/dev/build/tasks/os_packages/docker_generator/templates/kibana_yml.template.js
rename to src/dev/build/tasks/os_packages/docker_generator/templates/kibana_yml.template.ts
index c80f9334cfaeb..240ec6f4e9326 100644
--- a/src/dev/build/tasks/os_packages/docker_generator/templates/kibana_yml.template.js
+++ b/src/dev/build/tasks/os_packages/docker_generator/templates/kibana_yml.template.ts
@@ -19,7 +19,9 @@
import dedent from 'dedent';
-function generator({ imageFlavor }) {
+import { TemplateContext } from '../template_context';
+
+function generator({ imageFlavor }: TemplateContext) {
return dedent(`
#
# ** THIS IS AN AUTO-GENERATED FILE **
diff --git a/src/dev/build/tasks/os_packages/package_scripts/post_install.sh b/src/dev/build/tasks/os_packages/package_scripts/post_install.sh
index 10f11ff51874e..c49b291d1a0c9 100644
--- a/src/dev/build/tasks/os_packages/package_scripts/post_install.sh
+++ b/src/dev/build/tasks/os_packages/package_scripts/post_install.sh
@@ -3,6 +3,22 @@ set -e
export KBN_PATH_CONF=${KBN_PATH_CONF:-<%= configDir %>}
+set_chmod() {
+ chmod -f 660 ${KBN_PATH_CONF}/kibana.yml || true
+ chmod -f 2750 <%= dataDir %> || true
+ chmod -f 2750 ${KBN_PATH_CONF} || true
+}
+
+set_chown() {
+ chown -R <%= user %>:<%= group %> <%= dataDir %>
+ chown -R root:<%= group %> ${KBN_PATH_CONF}
+}
+
+set_access() {
+ set_chmod
+ set_chown
+}
+
case $1 in
# Debian
configure)
@@ -14,6 +30,8 @@ case $1 in
adduser --quiet --system --no-create-home --disabled-password \
--ingroup "<%= group %>" --shell /bin/false "<%= user %>"
fi
+
+ set_access
;;
abort-deconfigure|abort-upgrade|abort-remove)
;;
@@ -28,6 +46,8 @@ case $1 in
useradd -r -g "<%= group %>" -M -s /sbin/nologin \
-c "kibana service user" "<%= user %>"
fi
+
+ set_access
;;
*)
@@ -35,12 +55,3 @@ case $1 in
exit 1
;;
esac
-
-chown -R <%= user %>:<%= group %> <%= dataDir %>
-chmod 2750 <%= dataDir %>
-chmod -R 2755 <%= dataDir %>/*
-
-chown :<%= group %> ${KBN_PATH_CONF}
-chown :<%= group %> ${KBN_PATH_CONF}/kibana.yml
-chmod 2750 ${KBN_PATH_CONF}
-chmod 660 ${KBN_PATH_CONF}/kibana.yml
diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js
index e11668ab57f55..5249b7d652790 100644
--- a/src/dev/jest/config.js
+++ b/src/dev/jest/config.js
@@ -52,7 +52,6 @@ export default {
'!packages/kbn-ui-framework/src/services/**/*/index.js',
'src/legacy/core_plugins/**/*.{js,mjs,jsx,ts,tsx}',
'!src/legacy/core_plugins/**/{__test__,__snapshots__}/**/*',
- '!src/legacy/core_plugins/tests_bundle/**',
],
moduleNameMapper: {
'@elastic/eui$': '/node_modules/@elastic/eui/test-env',
diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js
index 1e4f048be8ea4..864bf7515053c 100644
--- a/src/dev/precommit_hook/casing_check_config.js
+++ b/src/dev/precommit_hook/casing_check_config.js
@@ -124,7 +124,6 @@ export const IGNORE_DIRECTORY_GLOBS = [
export const TEMPORARILY_IGNORED_PATHS = [
'src/legacy/core_plugins/console/public/src/directives/helpExample.txt',
'src/legacy/core_plugins/console/public/src/sense_editor/theme-sense-dark.js',
- 'src/legacy/core_plugins/tests_bundle/webpackShims/angular-mocks.js',
'src/legacy/core_plugins/tile_map/public/__tests__/scaledCircleMarkers.png',
'src/legacy/core_plugins/tile_map/public/__tests__/shadedCircleMarkers.png',
'src/legacy/core_plugins/tile_map/public/__tests__/shadedGeohashGrid.png',
diff --git a/src/legacy/core_plugins/tests_bundle/find_source_files.js b/src/legacy/core_plugins/tests_bundle/find_source_files.js
deleted file mode 100644
index eed88a5ecb8b0..0000000000000
--- a/src/legacy/core_plugins/tests_bundle/find_source_files.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { fromRoot } from '../../../core/server/utils';
-import { chain } from 'lodash';
-import { resolve } from 'path';
-import { fromNode } from 'bluebird';
-import glob from 'glob-all';
-
-const findSourceFiles = async (patterns, cwd = fromRoot('.')) => {
- patterns = [].concat(patterns || []);
-
- const matches = await fromNode((cb) => {
- glob(
- patterns,
- {
- cwd: cwd,
- ignore: [
- 'node_modules/**/*',
- 'bower_components/**/*',
- '**/_*.js',
- '**/*.test.js',
- '**/*.test.mocks.js',
- '**/__mocks__/**/*',
- ],
- symlinks: findSourceFiles.symlinks,
- statCache: findSourceFiles.statCache,
- realpathCache: findSourceFiles.realpathCache,
- cache: findSourceFiles.cache,
- },
- cb
- );
- });
-
- return chain(matches)
- .flatten()
- .uniq()
- .map((match) => resolve(cwd, match))
- .value();
-};
-
-findSourceFiles.symlinks = {};
-findSourceFiles.statCache = {};
-findSourceFiles.realpathCache = {};
-findSourceFiles.cache = {};
-
-export default findSourceFiles;
diff --git a/src/legacy/core_plugins/tests_bundle/index.js b/src/legacy/core_plugins/tests_bundle/index.js
deleted file mode 100644
index da7c1c4f4527e..0000000000000
--- a/src/legacy/core_plugins/tests_bundle/index.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { createReadStream } from 'fs';
-import { resolve } from 'path';
-
-import globby from 'globby';
-import MultiStream from 'multistream';
-import webpackMerge from 'webpack-merge';
-
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { fromRoot } from '../../../core/server/utils';
-import { replacePlaceholder } from '../../../optimize/public_path_placeholder';
-import findSourceFiles from './find_source_files';
-import { createTestEntryTemplate } from './tests_entry_template';
-
-export default (kibana) => {
- return new kibana.Plugin({
- config: (Joi) => {
- return Joi.object({
- enabled: Joi.boolean().default(true),
- instrument: Joi.boolean().default(false),
- pluginId: Joi.string(),
- }).default();
- },
-
- uiExports: {
- styleSheetPaths: resolve(__dirname, 'public/index.scss'),
- async __bundleProvider__(kbnServer) {
- const modules = new Set();
-
- const {
- config,
- uiApps,
- uiBundles,
- plugins,
- uiExports: { uiSettingDefaults = {} },
- } = kbnServer;
-
- const testGlobs = [];
-
- const testingPluginIds = config.get('tests_bundle.pluginId');
-
- if (testingPluginIds) {
- testingPluginIds.split(',').forEach((pluginId) => {
- const plugin = plugins.find((plugin) => plugin.id === pluginId);
-
- if (!plugin) {
- throw new Error('Invalid testingPluginId :: unknown plugin ' + pluginId);
- }
-
- // add the modules from all of this plugins apps
- for (const app of uiApps) {
- if (app.getPluginId() === pluginId) {
- modules.add(app.getMainModuleId());
- }
- }
-
- testGlobs.push(`${plugin.publicDir}/**/__tests__/**/*.js`);
- });
- } else {
- // add all since we are not just focused on specific plugins
- testGlobs.push('src/legacy/ui/public/**/*.js', '!src/legacy/ui/public/flot-charts/**/*');
- // add the modules from all of the apps
- for (const app of uiApps) {
- modules.add(app.getMainModuleId());
- }
-
- for (const plugin of plugins) {
- testGlobs.push(`${plugin.publicDir}/**/__tests__/**/*.js`);
- }
- }
-
- const testFiles = await findSourceFiles(testGlobs);
- for (const f of testFiles) modules.add(f);
-
- if (config.get('tests_bundle.instrument')) {
- uiBundles.addPostLoader({
- test: /\.js$/,
- exclude: /[\/\\](__tests__|node_modules|bower_components|webpackShims)[\/\\]/,
- loader: 'istanbul-instrumenter-loader',
- });
- }
-
- uiBundles.add({
- id: 'tests',
- modules: [...modules],
- template: createTestEntryTemplate(uiSettingDefaults),
- extendConfig(webpackConfig) {
- const mergedConfig = webpackMerge(
- {
- resolve: {
- extensions: ['.karma_mock.js', '.karma_mock.tsx', '.karma_mock.ts'],
- },
- node: {
- fs: 'empty',
- child_process: 'empty',
- dns: 'empty',
- net: 'empty',
- tls: 'empty',
- },
- },
- webpackConfig
- );
-
- /**
- * [..] it removes the commons bundle creation from the webpack
- * config when we're building the bundle for the browser tests. It
- * shouldn't be created, and by default isn't, but something is
- * triggering it in webpack which breaks the tests so if we just
- * remove the optimization config it will never happen and the tests
- * will keep working [..]
- *
- * TLDR: If you have any questions about this line, ask Spencer.
- */
- delete mergedConfig.optimization.splitChunks.cacheGroups.commons;
-
- return mergedConfig;
- },
- });
-
- kbnServer.server.route({
- method: 'GET',
- path: '/test_bundle/built_css.css',
- async handler(_, h) {
- const cssFiles = await globby(
- testingPluginIds
- ? testingPluginIds.split(',').map((id) => `built_assets/css/plugins/${id}/**/*.css`)
- : `built_assets/css/**/*.css`,
- { cwd: fromRoot('.'), absolute: true }
- );
-
- const stream = replacePlaceholder(
- new MultiStream(cssFiles.map((path) => createReadStream(path))),
- '/built_assets/css/'
- );
-
- return h.response(stream).code(200).type('text/css');
- },
- });
-
- // Sets global variables normally set by the bootstrap.js script
- kbnServer.server.route({
- path: '/test_bundle/karma/globals.js',
- method: 'GET',
- async handler(req, h) {
- const basePath = config.get('server.basePath');
-
- const file = `window.__kbnPublicPath__ = { 'kbn-ui-shared-deps': "${basePath}/bundles/kbn-ui-shared-deps/" };`;
-
- return h.response(file).header('content-type', 'application/json');
- },
- });
- },
-
- __globalImportAliases__: {
- ng_mock$: fromRoot('src/test_utils/public/ng_mock'),
- 'angular-mocks$': require.resolve('./webpackShims/angular-mocks'),
- fixtures: fromRoot('src/fixtures'),
- test_utils: fromRoot('src/test_utils/public'),
- },
- },
- });
-};
diff --git a/src/legacy/core_plugins/tests_bundle/package.json b/src/legacy/core_plugins/tests_bundle/package.json
deleted file mode 100644
index 4d2df048d4164..0000000000000
--- a/src/legacy/core_plugins/tests_bundle/package.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "tests_bundle",
- "version": "kibana"
-}
diff --git a/src/legacy/core_plugins/tests_bundle/public/index.scss b/src/legacy/core_plugins/tests_bundle/public/index.scss
deleted file mode 100644
index d8dbf8d6dc885..0000000000000
--- a/src/legacy/core_plugins/tests_bundle/public/index.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-// This file pulls some styles of NP plugins into the legacy test stylesheet
-// so they are available for karma browser tests.
-@import '../../../../plugins/vis_type_vislib/public/index';
-@import '../../../../plugins/visualizations/public/index';
diff --git a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js
deleted file mode 100644
index 28c26f08621eb..0000000000000
--- a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { Type } from '@kbn/config-schema';
-import pkg from '../../../../package.json';
-
-export const createTestEntryTemplate = (defaultUiSettings) => (bundle) => `
-/**
- * Test entry file
- *
- * This is programmatically created and updated, do not modify
- *
- * context: ${bundle.getContext()}
- *
- */
-
-import fetchMock from 'fetch-mock/es5/client';
-import { CoreSystem } from '__kibanaCore__';
-
-// Fake uiCapabilities returned to Core in browser tests
-const uiCapabilities = {
- navLinks: {
- myLink: true,
- notMyLink: true,
- },
- discover: {
- showWriteControls: true
- },
- visualize: {
- save: true
- },
- dashboard: {
- showWriteControls: true
- },
- timelion: {
- save: true
- },
- management: {
- kibana: {
- settings: true,
- index_patterns: true,
- objects: true
- }
- }
-};
-
-// Mock fetch for CoreSystem calls.
-fetchMock.config.fallbackToNetwork = true;
-fetchMock.post(/\\/api\\/core\\/capabilities/, {
- status: 200,
- body: JSON.stringify(uiCapabilities),
- headers: { 'Content-Type': 'application/json' },
-});
-
-// render the core system in a element not attached to the document as the
-// default children of the body in the browser tests are needed for mocha and
-// other test components to work
-const rootDomElement = document.createElement('div');
-
-const coreSystem = new CoreSystem({
- injectedMetadata: {
- version: '1.2.3',
- buildNumber: 1234,
- legacyMode: true,
- legacyMetadata: {
- app: {
- id: 'karma',
- title: 'Karma',
- },
- nav: [],
- version: '1.2.3',
- buildNum: 1234,
- devMode: true,
- uiSettings: {
- defaults: ${JSON.stringify(
- defaultUiSettings,
- (key, value) => {
- if (value instanceof Type) return null;
- return value;
- },
- 2
- )
- .split('\n')
- .join('\n ')},
- user: {}
- },
- nav: []
- },
- csp: {
- warnLegacyBrowsers: false,
- },
- capabilities: uiCapabilities,
- uiPlugins: [],
- vars: {
- kbnIndex: '.kibana',
- esShardTimeout: 1500,
- esApiVersion: ${JSON.stringify(pkg.branch)},
- esRequestTimeout: '300000',
- tilemapsConfig: {
- deprecated: {
- isOverridden: false,
- config: {
- options: {
- }
- }
- }
- },
- regionmapsConfig: {
- layers: []
- },
- mapConfig: {
- includeElasticMapsService: true,
- emsFileApiUrl: 'https://vector-staging.maps.elastic.co',
- emsTileApiUrl: 'https://tiles.maps.elastic.co',
- },
- vegaConfig: {
- enabled: true,
- enableExternalUrls: true
- },
- },
- },
- rootDomElement,
- requireLegacyBootstrapModule: () => {
- // wrapped in NODE_ENV check so the 'ui/test_harness' module
- // is not included in the distributable
- if (process.env.IS_KIBANA_DISTRIBUTABLE !== 'true') {
- return require('ui/test_harness');
- }
-
- throw new Error('tests bundle is not available in the distributable');
- },
- requireNewPlatformShimModule: () => require('ui/new_platform'),
- requireLegacyFiles: () => {
- ${bundle.getRequires().join('\n ')}
- }
-})
-
-coreSystem
- .setup()
- .then(() => {
- return coreSystem.start();
- });
-`;
diff --git a/src/legacy/core_plugins/tests_bundle/webpackShims/angular-mocks.js b/src/legacy/core_plugins/tests_bundle/webpackShims/angular-mocks.js
deleted file mode 100644
index 24f794cb32990..0000000000000
--- a/src/legacy/core_plugins/tests_bundle/webpackShims/angular-mocks.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-require('angular');
-require('../../../../../node_modules/angular-mocks/angular-mocks.js');
diff --git a/src/legacy/ui/public/test_harness/.eslintrc b/src/legacy/ui/public/test_harness/.eslintrc
deleted file mode 100644
index b1b85968796dd..0000000000000
--- a/src/legacy/ui/public/test_harness/.eslintrc
+++ /dev/null
@@ -1,2 +0,0 @@
-rules:
- no-console: 0
diff --git a/src/legacy/ui/public/test_harness/index.js b/src/legacy/ui/public/test_harness/index.js
deleted file mode 100644
index d66a4b1d67214..0000000000000
--- a/src/legacy/ui/public/test_harness/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export { bootstrap } from './test_harness';
diff --git a/src/legacy/ui/public/test_harness/test_harness.css b/src/legacy/ui/public/test_harness/test_harness.css
deleted file mode 100644
index d0a0f50c55b9b..0000000000000
--- a/src/legacy/ui/public/test_harness/test_harness.css
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * This file is only for tests so it is it's own CSS
- * to be imported directly by and only by this module.
- */
-
-body#test-harness-body {
- /**
- now that tests include the kibana styles, we have
- to override the body { display: flex; } rule as it
- prevents the visualizations from properly testing
- their sizing
- */
- display: block;
-}
-
-body#test-harness-body #mocha-stats .progress {
- /* bootstrap thinks it is the only one who will use ".progress" */
- height: auto;
- background-color: transparent;
- overflow: auto;
- border-radius: 0;
-}
diff --git a/src/legacy/ui/public/test_harness/test_harness.js b/src/legacy/ui/public/test_harness/test_harness.js
deleted file mode 100644
index 22c981fe0cf54..0000000000000
--- a/src/legacy/ui/public/test_harness/test_harness.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// chrome expects to be loaded first, let it get its way
-import chrome from '../chrome';
-
-import { parse as parseUrl } from 'url';
-import { Subject } from 'rxjs';
-import sinon from 'sinon';
-import { metadata } from '../metadata';
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { UiSettingsClient } from '../../../../core/public/ui_settings';
-
-import './test_harness.css';
-import 'ng_mock';
-import { setupTestSharding } from './test_sharding';
-
-const { query } = parseUrl(window.location.href, true);
-if (query && query.mocha) {
- try {
- window.mocha.setup(JSON.parse(query.mocha));
- } catch (error) {
- throw new Error(
- `'?mocha=${query.mocha}' query string param provided but it could not be parsed as json`
- );
- }
-}
-
-setupTestSharding();
-
-before(() => {
- // prevent accidental ajax requests
- sinon.useFakeXMLHttpRequest();
-});
-
-let stubUiSettings;
-let done$;
-function createStubUiSettings() {
- if (stubUiSettings) {
- done$.complete();
- }
- done$ = new Subject();
-
- stubUiSettings = new UiSettingsClient({
- api: {
- async batchSet() {
- return { settings: stubUiSettings.getAll() };
- },
- },
- onUpdateError: () => {},
- defaults: metadata.uiSettings.defaults,
- initialSettings: {},
- done$,
- });
-}
-
-createStubUiSettings();
-sinon.stub(chrome, 'getUiSettingsClient').callsFake(() => stubUiSettings);
-
-afterEach(function () {
- createStubUiSettings();
-});
-
-// Kick off mocha, called at the end of test entry files
-export function bootstrap(targetDomElement) {
- // allows test_harness.less to have higher priority selectors
- targetDomElement.setAttribute('id', 'test-harness-body');
-
- // load the hacks since we aren't actually bootstrapping the
- // chrome, which is where the hacks would normally be loaded
- require('uiExports/hacks');
- chrome.setupAngular();
-}
diff --git a/src/legacy/ui/public/test_harness/test_sharding/find_test_bundle_url.js b/src/legacy/ui/public/test_harness/test_sharding/find_test_bundle_url.js
deleted file mode 100644
index 53800d08ca05b..0000000000000
--- a/src/legacy/ui/public/test_harness/test_sharding/find_test_bundle_url.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/**
- * We don't have a lot of options for passing arguments to the page that karma
- * creates, so we tack some query string params onto the test bundle script url.
- *
- * This function finds that url by looking for a script tag that has
- * the "/tests.bundle.js" segment
- *
- * @return {string} url
- */
-export function findTestBundleUrl() {
- const scriptTags = document.querySelectorAll('script[src]');
- const scriptUrls = [].map.call(scriptTags, (el) => el.getAttribute('src'));
- const testBundleUrl = scriptUrls.find((url) => url.includes('/tests.bundle.js'));
-
- if (!testBundleUrl) {
- throw new Error("test bundle url couldn't be found");
- }
-
- return testBundleUrl;
-}
diff --git a/src/legacy/ui/public/test_harness/test_sharding/get_shard_num.js b/src/legacy/ui/public/test_harness/test_sharding/get_shard_num.js
deleted file mode 100644
index 55a33fc295191..0000000000000
--- a/src/legacy/ui/public/test_harness/test_sharding/get_shard_num.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import murmurHash3 from 'murmurhash3js';
-
-// murmur hashes are 32bit unsigned integers
-const MAX_HASH = Math.pow(2, 32);
-
-/**
- * Determine the shard number for a suite by hashing
- * its name and placing it based on the hash
- *
- * @param {number} shardTotal - the total number of shards
- * @param {string} suiteName - the suite name to hash
- * @return {number} shardNum - 1-based shard number
- */
-export function getShardNum(shardTotal, suiteName) {
- const hashIntsPerShard = MAX_HASH / shardTotal;
-
- const hashInt = murmurHash3.x86.hash32(suiteName);
-
- // murmur3 produces 32bit integers, so we devide it by the number of chunks
- // to determine which chunk the suite should fall in. +1 because the current
- // chunk is 1-based
- const shardNum = Math.floor(hashInt / hashIntsPerShard) + 1;
-
- // It's not clear if hash32 can produce the MAX_HASH or not,
- // but this just ensures that shard numbers don't go out of bounds
- // and cause tests to be ignored unnecessarily
- return Math.max(1, Math.min(shardNum, shardTotal));
-}
diff --git a/src/legacy/ui/public/test_harness/test_sharding/get_sharding_params_from_url.js b/src/legacy/ui/public/test_harness/test_sharding/get_sharding_params_from_url.js
deleted file mode 100644
index 65e41dbc84b63..0000000000000
--- a/src/legacy/ui/public/test_harness/test_sharding/get_sharding_params_from_url.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { parse as parseUrl } from 'url';
-
-/**
- * This function extracts the relevant "shards" and "shard_num"
- * params from the url.
- *
- * @param {string} testBundleUrl
- * @return {object} params
- * @property {number} params.shards - the total number of shards
- * @property {number} params.shard_num - the current shard number, 1 based
- */
-export function getShardingParamsFromUrl(url) {
- const parsedUrl = parseUrl(url, true);
- const parsedQuery = parsedUrl.query || {};
-
- const params = {};
- if (parsedQuery.shards) {
- params.shards = parseInt(parsedQuery.shards, 10);
- }
-
- if (parsedQuery.shard_num) {
- params.shard_num = parseInt(parsedQuery.shard_num, 10);
- }
-
- return params;
-}
diff --git a/src/legacy/ui/public/test_harness/test_sharding/index.js b/src/legacy/ui/public/test_harness/test_sharding/index.js
deleted file mode 100644
index cdca50725a058..0000000000000
--- a/src/legacy/ui/public/test_harness/test_sharding/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export { setupTestSharding } from './setup_test_sharding';
diff --git a/src/legacy/ui/public/test_harness/test_sharding/setup_test_sharding.js b/src/legacy/ui/public/test_harness/test_sharding/setup_test_sharding.js
deleted file mode 100644
index fce1876162387..0000000000000
--- a/src/legacy/ui/public/test_harness/test_sharding/setup_test_sharding.js
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { uniq, defaults } from 'lodash';
-
-import { findTestBundleUrl } from './find_test_bundle_url';
-import { getShardingParamsFromUrl } from './get_sharding_params_from_url';
-import { setupTopLevelDescribeFilter } from './setup_top_level_describe_filter';
-import { getShardNum } from './get_shard_num';
-
-const DEFAULT_PARAMS = {
- shards: 1,
- shard_num: 1,
-};
-
-export function setupTestSharding() {
- const pageUrl = window.location.href;
- const bundleUrl = findTestBundleUrl();
-
- // supports overriding params via the debug page
- // url in dev mode
- const params = defaults(
- {},
- getShardingParamsFromUrl(pageUrl),
- getShardingParamsFromUrl(bundleUrl),
- DEFAULT_PARAMS
- );
-
- const { shards: shardTotal, shard_num: shardNum } = params;
- if (shardNum < 1 || shardNum > shardTotal) {
- throw new TypeError(
- `shard_num param of ${shardNum} must be greater 0 and less than the total, ${shardTotal}`
- );
- }
-
- // track and log the number of ignored describe calls
- const ignoredDescribeShards = [];
- before(() => {
- const ignoredCount = ignoredDescribeShards.length;
- const ignoredFrom = uniq(ignoredDescribeShards).join(', ');
- console.log(`Ignored ${ignoredCount} top-level suites from ${ignoredFrom}`);
- });
-
- // Filter top-level describe statements as they come
- setupTopLevelDescribeFilter((describeName) => {
- const describeShardNum = getShardNum(shardTotal, describeName);
- if (describeShardNum === shardNum) return true;
- // track shard numbers that we ignore
- ignoredDescribeShards.push(describeShardNum);
- });
-
- console.log(`ready to load tests for shard ${shardNum} of ${shardTotal}`);
-}
diff --git a/src/legacy/ui/public/test_harness/test_sharding/setup_top_level_describe_filter.js b/src/legacy/ui/public/test_harness/test_sharding/setup_top_level_describe_filter.js
deleted file mode 100644
index 726f890077b94..0000000000000
--- a/src/legacy/ui/public/test_harness/test_sharding/setup_top_level_describe_filter.js
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/**
- * Intercept all calls to mocha.describe() and determine
- * which calls make it through using a filter function.
- *
- * The filter function is also only called for top-level
- * describe() calls; all describe calls nested within another
- * are allowed based on the filter value for the parent
- * describe
- *
- * ## example
- *
- * assume tests that look like this:
- *
- * ```js
- * describe('section 1', () => {
- * describe('item 1', () => {
- *
- * })
- * })
- * ```
- *
- * If the filter function returned true for "section 1" then "item 1"
- * would automatically be defined. If it returned false for "section 1"
- * then "section 1" would be ignored and "item 1" would never be defined
- *
- * @param {function} test - a function that takes the first argument
- * passed to describe, the sections name, and
- * returns true if the describe call should
- * be delegated to mocha, any other value causes
- * the describe call to be ignored
- * @return {undefined}
- */
-export function setupTopLevelDescribeFilter(test) {
- const originalDescribe = window.describe;
-
- if (!originalDescribe) {
- throw new TypeError(
- 'window.describe must be defined by mocha before test sharding can be setup'
- );
- }
-
- /**
- * When describe is called it is likely to make additional, nested,
- * calls to describe. We track how deeply nested we are at any time
- * with a depth counter, `describeCallDepth`.
- *
- * Before delegating a describe call to mocha we increment
- * that counter, and once mocha is done we decrement it.
- *
- * This way, we can check if `describeCallDepth > 0` at any time
- * to know if we are already within a describe call.
- *
- * ```js
- * // +1
- * describe('section 1', () => {
- * // describeCallDepth = 1
- * // +1
- * describe('item 1', () => {
- * // describeCallDepth = 2
- * })
- * // -1
- * })
- * // -1
- * // describeCallDepth = 0
- * ```
- *
- * @type {Number}
- */
- let describeCallDepth = 0;
-
- const describeInterceptor = function (describeName, describeBody) {
- const context = this;
-
- const isTopLevelCall = describeCallDepth === 0;
- const shouldIgnore = isTopLevelCall && Boolean(test(describeName)) === false;
- if (shouldIgnore) return;
-
- /**
- * we wrap the delegation to mocha in a try/finally block
- * to ensure that our describeCallDepth counter stays up
- * to date even if the call throws an error.
- *
- * note that try/finally won't actually catch the error, it
- * will continue to propagate up the call stack
- */
- let result;
- try {
- describeCallDepth += 1;
- result = originalDescribe.call(context, describeName, describeBody);
- } finally {
- describeCallDepth -= 1;
- }
- return result;
- };
-
- // to allow describe.only calls. we dont need interceptor as it will call describe internally
- describeInterceptor.only = originalDescribe.only;
- describeInterceptor.skip = originalDescribe.skip;
-
- // ensure that window.describe isn't messed with by other code
- Object.defineProperty(window, 'describe', {
- configurable: false,
- enumerable: true,
- value: describeInterceptor,
- });
-}
diff --git a/src/legacy/ui/ui_exports/ui_export_defaults.js b/src/legacy/ui/ui_exports/ui_export_defaults.js
index f7ee9aa056762..348f4ee77fab4 100644
--- a/src/legacy/ui/ui_exports/ui_export_defaults.js
+++ b/src/legacy/ui/ui_exports/ui_export_defaults.js
@@ -30,7 +30,6 @@ export const UI_EXPORT_DEFAULTS = {
webpackAliases: {
ui: resolve(ROOT, 'src/legacy/ui/public'),
__kibanaCore__$: resolve(ROOT, 'src/core/public'),
- test_harness: resolve(ROOT, 'src/test_harness/public'),
},
styleSheetPaths: ['light', 'dark'].map((theme) => ({
diff --git a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx
index 8987e190834d1..6a13cd16fc623 100644
--- a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx
+++ b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx
@@ -25,8 +25,8 @@ import React, { useState, ReactElement } from 'react';
import ReactDOM from 'react-dom';
import angular from 'angular';
-import { Subscription, merge } from 'rxjs';
-import { map, debounceTime } from 'rxjs/operators';
+import { Observable, pipe, Subscription, merge } from 'rxjs';
+import { filter, map, debounceTime, mapTo, startWith, switchMap } from 'rxjs/operators';
import { History } from 'history';
import { SavedObjectSaveOpts } from 'src/plugins/saved_objects/public';
import { NavigationPublicPluginStart as NavigationStart } from 'src/plugins/navigation/public';
@@ -259,11 +259,7 @@ export class DashboardAppController {
navActions[TopNavIds.VISUALIZE]();
};
- const updateIndexPatterns = (container?: DashboardContainer) => {
- if (!container || isErrorEmbeddable(container)) {
- return;
- }
-
+ function getDashboardIndexPatterns(container: DashboardContainer): IndexPattern[] {
let panelIndexPatterns: IndexPattern[] = [];
Object.values(container.getChildIds()).forEach((id) => {
const embeddableInstance = container.getChild(id);
@@ -273,19 +269,34 @@ export class DashboardAppController {
panelIndexPatterns.push(...embeddableIndexPatterns);
});
panelIndexPatterns = uniqBy(panelIndexPatterns, 'id');
+ return panelIndexPatterns;
+ }
- if (panelIndexPatterns && panelIndexPatterns.length > 0) {
- $scope.$evalAsync(() => {
- $scope.indexPatterns = panelIndexPatterns;
- });
- } else {
- indexPatterns.getDefault().then((defaultIndexPattern) => {
- $scope.$evalAsync(() => {
- $scope.indexPatterns = [defaultIndexPattern as IndexPattern];
- });
+ const updateIndexPatternsOperator = pipe(
+ filter((container: DashboardContainer) => !!container && !isErrorEmbeddable(container)),
+ map(getDashboardIndexPatterns),
+ // using switchMap for previous task cancellation
+ switchMap((panelIndexPatterns: IndexPattern[]) => {
+ return new Observable((observer) => {
+ if (panelIndexPatterns && panelIndexPatterns.length > 0) {
+ $scope.$evalAsync(() => {
+ if (observer.closed) return;
+ $scope.indexPatterns = panelIndexPatterns;
+ observer.complete();
+ });
+ } else {
+ indexPatterns.getDefault().then((defaultIndexPattern) => {
+ if (observer.closed) return;
+ $scope.$evalAsync(() => {
+ if (observer.closed) return;
+ $scope.indexPatterns = [defaultIndexPattern as IndexPattern];
+ observer.complete();
+ });
+ });
+ }
});
- }
- };
+ })
+ );
const getEmptyScreenProps = (
shouldShowEditHelp: boolean,
@@ -390,11 +401,17 @@ export class DashboardAppController {
) : null;
};
- updateIndexPatterns(dashboardContainer);
-
- outputSubscription = dashboardContainer.getOutput$().subscribe(() => {
- updateIndexPatterns(dashboardContainer);
- });
+ outputSubscription = new Subscription();
+ outputSubscription.add(
+ dashboardContainer
+ .getOutput$()
+ .pipe(
+ mapTo(dashboardContainer),
+ startWith(dashboardContainer), // to trigger initial index pattern update
+ updateIndexPatternsOperator
+ )
+ .subscribe()
+ );
inputSubscription = dashboardContainer.getInput$().subscribe(() => {
let dirty = false;
diff --git a/src/plugins/dashboard/public/index.ts b/src/plugins/dashboard/public/index.ts
index 17968dd0281e6..dcfde67cd9f13 100644
--- a/src/plugins/dashboard/public/index.ts
+++ b/src/plugins/dashboard/public/index.ts
@@ -32,7 +32,11 @@ export {
export { DashboardConstants, createDashboardEditUrl } from './dashboard_constants';
export { DashboardStart, DashboardUrlGenerator } from './plugin';
-export { DASHBOARD_APP_URL_GENERATOR, createDashboardUrlGenerator } from './url_generator';
+export {
+ DASHBOARD_APP_URL_GENERATOR,
+ createDashboardUrlGenerator,
+ DashboardUrlGeneratorState,
+} from './url_generator';
export { addEmbeddableToDashboardUrl } from './url_utils/url_helper';
export { SavedObjectDashboard } from './saved_dashboards';
export { SavedDashboardPanel } from './types';
diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx
index 041a02a251e8a..f0b57fec169fd 100644
--- a/src/plugins/dashboard/public/plugin.tsx
+++ b/src/plugins/dashboard/public/plugin.tsx
@@ -65,6 +65,7 @@ import {
ACTION_REPLACE_PANEL,
ClonePanelAction,
ClonePanelActionContext,
+ createDashboardContainerByValueRenderer,
DASHBOARD_CONTAINER_TYPE,
DashboardContainerFactory,
DashboardContainerFactoryDefinition,
@@ -77,17 +78,17 @@ import {
import {
createDashboardUrlGenerator,
DASHBOARD_APP_URL_GENERATOR,
- DashboardAppLinkGeneratorState,
+ DashboardUrlGeneratorState,
} from './url_generator';
import { createSavedDashboardLoader } from './saved_dashboards';
import { DashboardConstants } from './dashboard_constants';
import { addEmbeddableToDashboardUrl } from './url_utils/url_helper';
import { PlaceholderEmbeddableFactory } from './application/embeddable/placeholder';
-import { createDashboardContainerByValueRenderer } from './application';
+import { UrlGeneratorState } from '../../share/public';
declare module '../../share/public' {
export interface UrlGeneratorStateMapping {
- [DASHBOARD_APP_URL_GENERATOR]: DashboardAppLinkGeneratorState;
+ [DASHBOARD_APP_URL_GENERATOR]: UrlGeneratorState;
}
}
diff --git a/src/plugins/dashboard/public/url_generator.ts b/src/plugins/dashboard/public/url_generator.ts
index 188de7fd857be..68a50396e00d6 100644
--- a/src/plugins/dashboard/public/url_generator.ts
+++ b/src/plugins/dashboard/public/url_generator.ts
@@ -26,7 +26,7 @@ import {
RefreshInterval,
} from '../../data/public';
import { setStateToKbnUrl } from '../../kibana_utils/public';
-import { UrlGeneratorsDefinition, UrlGeneratorState } from '../../share/public';
+import { UrlGeneratorsDefinition } from '../../share/public';
import { SavedObjectLoader } from '../../saved_objects/public';
import { ViewMode } from '../../embeddable/public';
@@ -35,7 +35,7 @@ export const GLOBAL_STATE_STORAGE_KEY = '_g';
export const DASHBOARD_APP_URL_GENERATOR = 'DASHBOARD_APP_URL_GENERATOR';
-export type DashboardAppLinkGeneratorState = UrlGeneratorState<{
+export interface DashboardUrlGeneratorState {
/**
* If given, the dashboard saved object with this id will be loaded. If not given,
* a new, unsaved dashboard will be loaded up.
@@ -79,7 +79,7 @@ export type DashboardAppLinkGeneratorState = UrlGeneratorState<{
* View mode of the dashboard.
*/
viewMode?: ViewMode;
-}>;
+}
export const createDashboardUrlGenerator = (
getStartServices: () => Promise<{
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 846471420327f..e95150e8f6f73 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -58,6 +58,7 @@ import {
changeTimeFilter,
mapAndFlattenFilters,
extractTimeFilter,
+ extractTimeRange,
convertRangeFilterToTimeRangeString,
} from './query';
@@ -99,6 +100,7 @@ export const esFilters = {
convertRangeFilterToTimeRangeString,
mapAndFlattenFilters,
extractTimeFilter,
+ extractTimeRange,
};
export {
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index d62123387fa04..c231877c9d930 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -500,6 +500,7 @@ export const esFilters: {
convertRangeFilterToTimeRangeString: typeof convertRangeFilterToTimeRangeString;
mapAndFlattenFilters: (filters: import("../common").Filter[]) => import("../common").Filter[];
extractTimeFilter: typeof extractTimeFilter;
+ extractTimeRange: typeof extractTimeRange;
};
// Warning: (ae-missing-release-tag) "esKuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
diff --git a/src/plugins/data/public/query/timefilter/index.ts b/src/plugins/data/public/query/timefilter/index.ts
index 19386c10ab59f..dc9a4ef8c21a6 100644
--- a/src/plugins/data/public/query/timefilter/index.ts
+++ b/src/plugins/data/public/query/timefilter/index.ts
@@ -23,5 +23,5 @@ export * from './types';
export { Timefilter, TimefilterContract } from './timefilter';
export { TimeHistory, TimeHistoryContract } from './time_history';
export { changeTimeFilter, convertRangeFilterToTimeRangeString } from './lib/change_time_filter';
-export { extractTimeFilter } from './lib/extract_time_filter';
+export { extractTimeFilter, extractTimeRange } from './lib/extract_time_filter';
export { validateTimeRange } from './lib/validate_timerange';
diff --git a/src/plugins/data/public/query/timefilter/lib/extract_time_filter.ts b/src/plugins/data/public/query/timefilter/lib/extract_time_filter.ts
index 23dd1547baf10..2f93196e3218b 100644
--- a/src/plugins/data/public/query/timefilter/lib/extract_time_filter.ts
+++ b/src/plugins/data/public/query/timefilter/lib/extract_time_filter.ts
@@ -18,7 +18,8 @@
*/
import { keys, partition } from 'lodash';
-import { Filter, isRangeFilter, RangeFilter } from '../../../../common';
+import { Filter, isRangeFilter, RangeFilter, TimeRange } from '../../../../common';
+import { convertRangeFilterToTimeRangeString } from './change_time_filter';
export function extractTimeFilter(timeFieldName: string, filters: Filter[]) {
const [timeRangeFilter, restOfFilters] = partition(filters, (obj: Filter) => {
@@ -36,3 +37,15 @@ export function extractTimeFilter(timeFieldName: string, filters: Filter[]) {
timeRangeFilter: timeRangeFilter[0] as RangeFilter | undefined,
};
}
+
+export function extractTimeRange(
+ filters: Filter[],
+ timeFieldName?: string
+): { restOfFilters: Filter[]; timeRange?: TimeRange } {
+ if (!timeFieldName) return { restOfFilters: filters, timeRange: undefined };
+ const { timeRangeFilter, restOfFilters } = extractTimeFilter(timeFieldName, filters);
+ return {
+ restOfFilters,
+ timeRange: timeRangeFilter ? convertRangeFilterToTimeRangeString(timeRangeFilter) : undefined,
+ };
+}
diff --git a/src/plugins/inspector/public/views/data/components/data_view.test.tsx b/src/plugins/inspector/public/views/data/components/data_view.test.tsx
index 2772069d36877..bd78bca42c479 100644
--- a/src/plugins/inspector/public/views/data/components/data_view.test.tsx
+++ b/src/plugins/inspector/public/views/data/components/data_view.test.tsx
@@ -51,13 +51,13 @@ describe('Inspector Data View', () => {
});
it('should render loading state', () => {
- const component = mountWithIntl();
+ const component = mountWithIntl(); // eslint-disable-line react/jsx-pascal-case
expect(component).toMatchSnapshot();
});
it('should render empty state', async () => {
- const component = mountWithIntl();
+ const component = mountWithIntl(); // eslint-disable-line react/jsx-pascal-case
const tabularLoader = Promise.resolve(null);
adapters.data.setTabularLoader(() => tabularLoader);
await tabularLoader;
diff --git a/tasks/config/karma.js b/tasks/config/karma.js
deleted file mode 100644
index 114e09876406c..0000000000000
--- a/tasks/config/karma.js
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { dirname } from 'path';
-import { times } from 'lodash';
-import { makeJunitReportPath } from '@kbn/test';
-import * as UiSharedDeps from '@kbn/ui-shared-deps';
-
-const TOTAL_CI_SHARDS = 4;
-const ROOT = dirname(require.resolve('../../package.json'));
-const buildHash = String(Number.MAX_SAFE_INTEGER);
-
-module.exports = function (grunt) {
- function pickBrowser() {
- if (grunt.option('browser')) {
- return grunt.option('browser');
- }
- if (process.env.TEST_BROWSER_HEADLESS === '1') {
- return 'Chrome_Headless';
- }
- return 'Chrome';
- }
-
- function pickReporters() {
- // available reporters: https://npmjs.org/browse/keyword/karma-reporter
- if (process.env.CI && process.env.DISABLE_JUNIT_REPORTER) {
- return ['dots'];
- }
-
- if (process.env.CI) {
- return ['dots', 'junit'];
- }
-
- return ['progress'];
- }
-
- function getKarmaFiles(shardNum) {
- return [
- 'http://localhost:5610/test_bundle/built_css.css',
- // Sets global variables normally set by the bootstrap.js script
- 'http://localhost:5610/test_bundle/karma/globals.js',
-
- ...UiSharedDeps.jsDepFilenames.map(
- (chunkFilename) =>
- `http://localhost:5610/${buildHash}/bundles/kbn-ui-shared-deps/${chunkFilename}`
- ),
- `http://localhost:5610/${buildHash}/bundles/kbn-ui-shared-deps/${UiSharedDeps.jsFilename}`,
-
- shardNum === undefined
- ? `http://localhost:5610/${buildHash}/bundles/tests.bundle.js`
- : `http://localhost:5610/${buildHash}/bundles/tests.bundle.js?shards=${TOTAL_CI_SHARDS}&shard_num=${shardNum}`,
-
- `http://localhost:5610/${buildHash}/bundles/kbn-ui-shared-deps/${UiSharedDeps.baseCssDistFilename}`,
- // this causes tilemap tests to fail, probably because the eui styles haven't been
- // included in the karma harness a long some time, if ever
- // `http://localhost:5610/bundles/kbn-ui-shared-deps/${UiSharedDeps.lightCssDistFilename}`,
- `http://localhost:5610/${buildHash}/bundles/tests.style.css`,
- ];
- }
-
- const config = {
- options: {
- // base path that will be used to resolve all patterns (eg. files, exclude)
- basePath: '',
-
- captureTimeout: 30000,
- browserNoActivityTimeout: 120000,
- frameworks: ['mocha'],
- plugins: [
- 'karma-chrome-launcher',
- 'karma-coverage',
- 'karma-firefox-launcher',
- 'karma-ie-launcher',
- 'karma-junit-reporter',
- 'karma-mocha',
- 'karma-safari-launcher',
- ],
- port: 9876,
- colors: true,
- logLevel: grunt.option('debug') || grunt.option('verbose') ? 'DEBUG' : 'INFO',
- autoWatch: false,
- browsers: [pickBrowser()],
- customLaunchers: {
- Chrome_Headless: {
- base: 'Chrome',
- flags: ['--headless', '--disable-gpu', '--remote-debugging-port=9222'],
- },
- },
-
- reporters: pickReporters(),
-
- junitReporter: {
- outputFile: makeJunitReportPath(ROOT, 'karma'),
- useBrowserName: false,
- nameFormatter: (_, result) => [...result.suite, result.description].join(' '),
- classNameFormatter: (_, result) => {
- const rootSuite = result.suite[0] || result.description;
- return `Browser Unit Tests.${rootSuite.replace(/\./g, '·')}`;
- },
- },
-
- // list of files / patterns to load in the browser
- files: getKarmaFiles(),
-
- proxies: {
- '/tests/': 'http://localhost:5610/tests/',
- '/test_bundle/': 'http://localhost:5610/test_bundle/',
- [`/${buildHash}/bundles/`]: `http://localhost:5610/${buildHash}/bundles/`,
- },
-
- client: {
- mocha: {
- reporter: 'html', // change Karma's debug.html to the mocha web reporter
- timeout: 10000,
- slow: 5000,
- },
- },
- },
-
- dev: { singleRun: false },
- unit: { singleRun: true },
- coverage: {
- singleRun: true,
- reporters: ['coverage'],
- coverageReporter: {
- reporters: [{ type: 'html', dir: 'coverage' }, { type: 'text-summary' }],
- },
- },
- };
-
- /**
- * ------------------------------------------------------------
- * CI sharding
- * ------------------------------------------------------------
- *
- * Every test retains nearly all of the memory it causes to be allocated,
- * which has started to kill the test browser as the size of the test suite
- * increases. This is a deep-rooted problem that will take some serious
- * work to fix.
- *
- * CI sharding is a short-term solution that splits the top-level describe
- * calls into different "shards" and instructs karma to only run one shard
- * at a time, reloading the browser in between each shard and forcing the
- * memory from the previous shard to be released.
- *
- * ## how
- *
- * Rather than modify the bundling process to produce multiple testing
- * bundles, top-level describe calls are sharded by their first argument,
- * the suite name.
- *
- * The number of shards to create is controlled with the TOTAL_CI_SHARDS
- * constant defined at the top of this file.
- *
- * ## controlling sharding
- *
- * To control sharding in a specific karma configuration, the total number
- * of shards to create (?shards=X), and the current shard number
- * (&shard_num=Y), are added to the testing bundle url and read by the
- * test_harness/setup_test_sharding[1] module. This allows us to use a
- * different number of shards in different scenarios (ie. running
- * `yarn test:karma` runs the tests in a single shard, effectively
- * disabling sharding)
- *
- * These same parameters can also be defined in the URL/query string of the
- * karma debug page (started when you run `yarn test:karma:debug`).
- *
- * ## debugging
- *
- * It is *possible* that some tests will only pass if run after/with certain
- * other suites. To debug this, make sure that your tests pass in isolation
- * (by clicking the suite name on the karma debug page) and that it runs
- * correctly in it's given shard (using the `?shards=X&shard_num=Y` query
- * string params on the karma debug page). You can spot the shard number
- * a test is running in by searching for the "ready to load tests for shard X"
- * log message.
- *
- * [1]: src/legacy/ui/public/test_harness/test_sharding/setup_test_sharding.js
- */
- times(TOTAL_CI_SHARDS, (i) => {
- const n = i + 1;
- config[`ciShard-${n}`] = {
- singleRun: true,
- options: {
- files: getKarmaFiles(n),
- },
- };
- });
-
- return config;
-};
diff --git a/tasks/config/run.js b/tasks/config/run.js
index 98a1226834bc6..9ac8f72d56d4a 100644
--- a/tasks/config/run.js
+++ b/tasks/config/run.js
@@ -17,7 +17,6 @@
* under the License.
*/
-import { resolve } from 'path';
import { getFunctionalTestGroupRunConfigs } from '../function_test_groups';
const { version } = require('../../package.json');
@@ -25,44 +24,7 @@ const KIBANA_INSTALL_DIR =
process.env.KIBANA_INSTALL_DIR ||
`./build/oss/kibana-${version}-SNAPSHOT-${process.platform}-x86_64`;
-module.exports = function (grunt) {
- function createKbnServerTask({ runBuild, flags = [] }) {
- return {
- options: {
- wait: false,
- ready: /http server running/,
- quiet: false,
- failOnError: false,
- },
- cmd: runBuild ? `./build/${runBuild}/bin/kibana` : process.execPath,
- args: [
- ...(runBuild ? [] : [require.resolve('../../scripts/kibana'), '--oss']),
-
- '--logging.json=false',
-
- ...flags,
-
- // allow the user to override/inject flags by defining cli args starting with `--kbnServer.`
- ...grunt.option.flags().reduce(function (flags, flag) {
- if (flag.startsWith('--kbnServer.')) {
- flags.push(`--${flag.slice(12)}`);
- }
-
- return flags;
- }, []),
- ],
- };
- }
-
- const karmaTestServerFlags = [
- '--env.name=development',
- '--plugins.initialize=false',
- '--optimize.bundleFilter=tests',
- '--optimize.validateSyntaxOfNodeModules=false',
- '--server.port=5610',
- '--migrations.skip=true',
- ];
-
+module.exports = function () {
const NODE = 'node';
const YARN = 'yarn';
const scriptWithGithubChecks = ({ title, options, cmd, args }) =>
@@ -177,37 +139,6 @@ module.exports = function (grunt) {
],
}),
- // used by the test:karma task
- // runs the kibana server to serve the browser test bundle
- karmaTestServer: createKbnServerTask({
- flags: [...karmaTestServerFlags],
- }),
- browserSCSS: createKbnServerTask({
- flags: [...karmaTestServerFlags, '--optimize', '--optimize.enabled=false'],
- }),
-
- // used by the test:coverage task
- // runs the kibana server to serve the instrumented version of the browser test bundle
- karmaTestCoverageServer: createKbnServerTask({
- flags: [...karmaTestServerFlags, '--tests_bundle.instrument=true'],
- }),
-
- // used by the test:karma:debug task
- // runs the kibana server to serve the browser test bundle, but listens for changes
- // to the public/browser code and rebuilds the test bundle on changes
- karmaTestDebugServer: createKbnServerTask({
- flags: [
- ...karmaTestServerFlags,
- '--dev',
- '--no-dev-config',
- '--no-watch',
- '--no-base-path',
- '--optimize.watchPort=5611',
- '--optimize.watchPrebuild=true',
- '--optimize.bundleDir=' + resolve(__dirname, '../../data/optimize/testdev'),
- ],
- }),
-
verifyNotice: scriptWithGithubChecks({
title: 'Verify NOTICE.txt',
options: {
@@ -325,7 +256,6 @@ module.exports = function (grunt) {
'test:jest_integration'
),
test_projects: gruntTaskWithGithubChecks('Project tests', 'test:projects'),
- test_karma_ci: gruntTaskWithGithubChecks('Browser tests', 'test:karma-ci'),
...getFunctionalTestGroupRunConfigs({
kibanaInstallDir: KIBANA_INSTALL_DIR,
diff --git a/tasks/jenkins.js b/tasks/jenkins.js
index eece5df61a7d1..adfb6f0f46868 100644
--- a/tasks/jenkins.js
+++ b/tasks/jenkins.js
@@ -37,7 +37,6 @@ module.exports = function (grunt) {
'run:test_jest',
'run:test_jest_integration',
'run:test_projects',
- 'run:test_karma_ci',
'run:test_hardening',
'run:test_package_safer_lodash_set',
'run:apiIntegrationTests',
diff --git a/tasks/test.js b/tasks/test.js
index 09821b97fe2e8..f370ea0b948c6 100644
--- a/tasks/test.js
+++ b/tasks/test.js
@@ -17,8 +17,6 @@
* under the License.
*/
-import _, { keys } from 'lodash';
-
import { run } from '../utilities/visual_regression';
module.exports = function (grunt) {
@@ -31,25 +29,6 @@ module.exports = function (grunt) {
}
);
- grunt.registerTask('test:karma', [
- 'checkPlugins',
- 'run:browserSCSS',
- 'run:karmaTestServer',
- 'karma:unit',
- ]);
-
- grunt.registerTask('test:karma-ci', () => {
- const ciShardTasks = keys(grunt.config.get('karma'))
- .filter((key) => key.startsWith('ciShard-'))
- .map((key) => `karma:${key}`);
-
- grunt.log.ok(`Running UI tests in ${ciShardTasks.length} shards`);
- grunt.task.run(['run:browserSCSS']);
- grunt.task.run(['run:karmaTestServer', ...ciShardTasks]);
- });
-
- grunt.registerTask('test:coverage', ['run:karmaTestCoverageServer', 'karma:coverage']);
-
grunt.registerTask('test:quick', [
'checkPlugins',
'run:mocha',
@@ -57,18 +36,16 @@ module.exports = function (grunt) {
'test:jest',
'test:jest_integration',
'test:projects',
- 'test:karma',
'run:apiIntegrationTests',
]);
- grunt.registerTask('test:karmaDebug', ['checkPlugins', 'run:karmaTestDebugServer', 'karma:dev']);
grunt.registerTask('test:mochaCoverage', ['run:mochaCoverage']);
grunt.registerTask('test', (subTask) => {
if (subTask) grunt.fail.fatal(`invalid task "test:${subTask}"`);
grunt.task.run(
- _.compact([
+ [
!grunt.option('quick') && 'run:eslint',
!grunt.option('quick') && 'run:sasslint',
!grunt.option('quick') && 'run:checkTsProjects',
@@ -78,7 +55,7 @@ module.exports = function (grunt) {
'run:checkFileCasing',
'run:licenses',
'test:quick',
- ])
+ ].filter(Boolean)
);
});
diff --git a/test/common/services/elasticsearch.ts b/test/common/services/elasticsearch.ts
index 0436dc901292d..a01f9ff3c8da5 100644
--- a/test/common/services/elasticsearch.ts
+++ b/test/common/services/elasticsearch.ts
@@ -27,11 +27,18 @@ import { FtrProviderContext } from '../ftr_provider_context';
export function ElasticsearchProvider({ getService }: FtrProviderContext) {
const config = getService('config');
- return new Client({
- ssl: {
- ca: fs.readFileSync(CA_CERT_PATH, 'utf-8'),
- },
- nodes: [formatUrl(config.get('servers.elasticsearch'))],
- requestTimeout: config.get('timeouts.esRequestTimeout'),
- });
+ if (process.env.TEST_CLOUD) {
+ return new Client({
+ nodes: [formatUrl(config.get('servers.elasticsearch'))],
+ requestTimeout: config.get('timeouts.esRequestTimeout'),
+ });
+ } else {
+ return new Client({
+ ssl: {
+ ca: fs.readFileSync(CA_CERT_PATH, 'utf-8'),
+ },
+ nodes: [formatUrl(config.get('servers.elasticsearch'))],
+ requestTimeout: config.get('timeouts.esRequestTimeout'),
+ });
+ }
}
diff --git a/test/functional/apps/visualize/_gauge_chart.js b/test/functional/apps/visualize/_gauge_chart.js
index aa94e596319c2..0f870b1fb545f 100644
--- a/test/functional/apps/visualize/_gauge_chart.js
+++ b/test/functional/apps/visualize/_gauge_chart.js
@@ -26,7 +26,6 @@ export default function ({ getService, getPageObjects }) {
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['visualize', 'visEditor', 'visChart', 'timePicker']);
- // FLAKY: https://github.com/elastic/kibana/issues/45089
describe('gauge chart', function indexPatternCreation() {
async function initGaugeVis() {
log.debug('navigateToApp visualize');
diff --git a/test/functional/page_objects/timelion_page.ts b/test/functional/page_objects/timelion_page.ts
index f025fc946bef1..23a9cc514a444 100644
--- a/test/functional/page_objects/timelion_page.ts
+++ b/test/functional/page_objects/timelion_page.ts
@@ -47,7 +47,7 @@ export function TimelionPageProvider({ getService, getPageObjects }: FtrProvider
public async updateExpression(updates: string) {
const input = await testSubjects.find('timelionExpressionTextArea');
await input.type(updates);
- await PageObjects.common.sleep(500);
+ await PageObjects.common.sleep(1000);
}
public async getExpression() {
@@ -60,7 +60,7 @@ export function TimelionPageProvider({ getService, getPageObjects }: FtrProvider
return await Promise.all(elements.map(async (element) => await element.getVisibleText()));
}
- public async clickSuggestion(suggestionIndex = 0, waitTime = 500) {
+ public async clickSuggestion(suggestionIndex = 0, waitTime = 1000) {
const elements = await testSubjects.findAll('timelionSuggestionListItem');
if (suggestionIndex > elements.length) {
throw new Error(
diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts
index 0db8cac0f0758..8488eb8cd2749 100644
--- a/test/functional/page_objects/visual_builder_page.ts
+++ b/test/functional/page_objects/visual_builder_page.ts
@@ -408,7 +408,7 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro
* @memberof VisualBuilderPage
*/
public async getViewTable(): Promise {
- const tableView = await testSubjects.find('tableView');
+ const tableView = await testSubjects.find('tableView', 20000);
return await tableView.getVisibleText();
}
diff --git a/test/functional/services/combo_box.ts b/test/functional/services/combo_box.ts
index 60fea7ea86cf9..ac7a40361d065 100644
--- a/test/functional/services/combo_box.ts
+++ b/test/functional/services/combo_box.ts
@@ -90,7 +90,7 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
await this.clickOption(options.clickWithMouse, selectOptions[0]);
} else {
// if it doesn't find the item which text starts with value, it will choose the first option
- const firstOption = await find.byCssSelector('.euiFilterSelectItem');
+ const firstOption = await find.byCssSelector('.euiFilterSelectItem', 5000);
await this.clickOption(options.clickWithMouse, firstOption);
}
} else {
diff --git a/test/plugin_functional/plugins/core_app_status/public/plugin.tsx b/test/plugin_functional/plugins/core_app_status/public/plugin.tsx
index af23bfbe1f8f5..bdc08c03c1912 100644
--- a/test/plugin_functional/plugins/core_app_status/public/plugin.tsx
+++ b/test/plugin_functional/plugins/core_app_status/public/plugin.tsx
@@ -26,6 +26,7 @@ import {
CoreStart,
AppMountParameters,
} from 'kibana/public';
+import { renderApp } from './application';
import './types';
export class CoreAppStatusPlugin implements Plugin<{}, CoreAppStatusPluginStart> {
@@ -36,7 +37,6 @@ export class CoreAppStatusPlugin implements Plugin<{}, CoreAppStatusPluginStart>
id: 'app_status_start',
title: 'App Status Start Page',
async mount(params: AppMountParameters) {
- const { renderApp } = await import('./application');
return renderApp('app_status_start', params);
},
});
@@ -47,7 +47,6 @@ export class CoreAppStatusPlugin implements Plugin<{}, CoreAppStatusPluginStart>
euiIconType: 'snowflake',
updater$: this.appUpdater,
async mount(params: AppMountParameters) {
- const { renderApp } = await import('./application');
return renderApp('app_status', params);
},
});
diff --git a/test/plugin_functional/test_suites/core_plugins/application_status.ts b/test/plugin_functional/test_suites/core_plugins/application_status.ts
index 31a1c28b50842..a4c2db733b894 100644
--- a/test/plugin_functional/test_suites/core_plugins/application_status.ts
+++ b/test/plugin_functional/test_suites/core_plugins/application_status.ts
@@ -41,6 +41,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
const PageObjects = getPageObjects(['common']);
const browser = getService('browser');
const appsMenu = getService('appsMenu');
+ const retry = getService('retry');
const testSubjects = getService('testSubjects');
const setAppStatus = async (s: Partial) => {
@@ -50,15 +51,14 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
}, s);
};
- const navigateToApp = async (i: string) => {
+ const navigateToApp = async (id: string) => {
return await browser.executeAsync(async (appId, cb) => {
await window.__coreAppStatus.navigateToApp(appId);
cb();
- }, i);
+ }, id);
};
- // FLAKY: https://github.com/elastic/kibana/issues/65423
- describe.skip('application status management', () => {
+ describe('application status management', () => {
beforeEach(async () => {
await PageObjects.common.navigateToApp('app_status_start');
});
@@ -101,15 +101,17 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
});
it('allows to change the defaultPath of an application', async () => {
- let link = await appsMenu.getLink('App Status');
+ const link = await appsMenu.getLink('App Status');
expect(link!.href).to.eql(getKibanaUrl('/app/app_status'));
await setAppStatus({
defaultPath: '/arbitrary/path',
});
- link = await appsMenu.getLink('App Status');
- expect(link!.href).to.eql(getKibanaUrl('/app/app_status/arbitrary/path'));
+ await retry.waitFor('link url updated with "defaultPath"', async () => {
+ const updatedLink = await appsMenu.getLink('App Status');
+ return updatedLink?.href === getKibanaUrl('/app/app_status/arbitrary/path');
+ });
await navigateToApp('app_status');
expect(await testSubjects.exists('appStatusApp')).to.eql(true);
diff --git a/test/scripts/jenkins_xpack.sh b/test/scripts/jenkins_xpack.sh
index bc927b1ed7b4d..77480554f738c 100755
--- a/test/scripts/jenkins_xpack.sh
+++ b/test/scripts/jenkins_xpack.sh
@@ -3,9 +3,9 @@
source test/scripts/jenkins_test_setup.sh
if [[ -z "$CODE_COVERAGE" ]] ; then
- echo " -> Running mocha tests"
- cd "$XPACK_DIR"
- checks-reporter-with-killswitch "X-Pack Karma Tests" yarn test:karma
+ echo " -> Building legacy styles for x-pack canvas storyshot tests"
+ cd "$KIBANA_DIR"
+ node scripts/build_sass
echo ""
echo ""
diff --git a/x-pack/README.md b/x-pack/README.md
index 03d2e3287c0f0..0449f1fc1bdab 100644
--- a/x-pack/README.md
+++ b/x-pack/README.md
@@ -44,14 +44,6 @@ If you want to run tests only for a specific plugin (to save some time), you can
yarn test --plugins [,]* # where is "reporting", etc.
```
-#### Debugging browser tests
-```
-yarn test:karma:debug
-```
-Initializes an environment for debugging the browser tests. Includes an dedicated instance of the kibana server for building the test bundle, and a karma server. When running this task the build is optimized for the first time and then a karma-owned instance of the browser is opened. Click the "debug" button to open a new tab that executes the unit tests.
-
-Run single tests by appending `grep` parameter to the end of the URL. For example `http://localhost:9876/debug.html?grep=ML%20-%20Explorer%20Controller` will only run tests with 'ML - Explorer Controller' in the describe block.
-
#### Running server unit tests
You can run mocha unit tests by running:
diff --git a/x-pack/gulpfile.js b/x-pack/gulpfile.js
index 7e5ab9b18f019..78ed2bff8cb01 100644
--- a/x-pack/gulpfile.js
+++ b/x-pack/gulpfile.js
@@ -8,7 +8,6 @@ require('../src/setup_node_env');
const { buildTask } = require('./tasks/build');
const { devTask } = require('./tasks/dev');
-const { testTask, testKarmaTask, testKarmaDebugTask } = require('./tasks/test');
const { downloadChromium } = require('./tasks/download_chromium');
// export the tasks that are runnable from the CLI
@@ -16,7 +15,4 @@ module.exports = {
build: buildTask,
dev: devTask,
downloadChromium,
- test: testTask,
- 'test:karma': testKarmaTask,
- 'test:karma:debug': testKarmaDebugTask,
};
diff --git a/x-pack/package.json b/x-pack/package.json
index 39bdb76ac7a73..76655f75cadcc 100644
--- a/x-pack/package.json
+++ b/x-pack/package.json
@@ -11,8 +11,6 @@
"build": "gulp build",
"testonly": "echo 'Deprecated, use `yarn test`' && gulp test",
"test": "gulp test",
- "test:karma:debug": "gulp test:karma:debug",
- "test:karma": "gulp test:karma",
"test:jest": "node scripts/jest",
"test:mocha": "node scripts/mocha"
},
@@ -133,7 +131,7 @@
"cheerio": "0.22.0",
"commander": "3.0.2",
"copy-webpack-plugin": "^6.0.2",
- "cypress": "4.5.0",
+ "cypress": "4.11.0",
"cypress-multi-reporters": "^1.2.3",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
@@ -284,6 +282,7 @@
"json-stable-stringify": "^1.0.1",
"jsonwebtoken": "^8.5.1",
"jsts": "^1.6.2",
+ "kea": "^2.0.1",
"lodash": "^4.17.15",
"lz-string": "^1.4.4",
"mapbox-gl": "^1.10.0",
@@ -386,4 +385,4 @@
"cypress-multi-reporters"
]
}
-}
\ No newline at end of file
+}
diff --git a/x-pack/plugins/apm/e2e/cypress/plugins/index.js b/x-pack/plugins/apm/e2e/cypress/plugins/index.js
index 540b887d55df5..c5529c747adcd 100644
--- a/x-pack/plugins/apm/e2e/cypress/plugins/index.js
+++ b/x-pack/plugins/apm/e2e/cypress/plugins/index.js
@@ -29,6 +29,8 @@ module.exports = (on) => {
// readFileMaybe
on('task', {
+ // ESLint thinks this is a react component for some reason.
+ // eslint-disable-next-line react/function-component-definition
readFileMaybe(filename) {
if (fs.existsSync(filename)) {
return fs.readFileSync(filename, 'utf8');
diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx
index c39afe6da215e..0c9c6eb86225b 100644
--- a/x-pack/plugins/apm/public/application/index.tsx
+++ b/x-pack/plugins/apm/public/application/index.tsx
@@ -37,7 +37,7 @@ const MainContainer = styled.div`
height: 100%;
`;
-const App = () => {
+function App() {
const [darkMode] = useUiSetting$('theme:darkMode');
return (
@@ -59,9 +59,9 @@ const App = () => {
);
-};
+}
-const ApmAppRoot = ({
+function ApmAppRoot({
core,
deps,
routerHistory,
@@ -71,7 +71,7 @@ const ApmAppRoot = ({
deps: ApmPluginSetupDeps;
routerHistory: typeof history;
config: ConfigSchema;
-}) => {
+}) {
const i18nCore = core.i18n;
const plugins = deps;
const apmPluginContextValue = {
@@ -111,7 +111,7 @@ const ApmAppRoot = ({
);
-};
+}
/**
* This module is rendered asynchronously in the Kibana platform.
diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx
index 1096c0c77db30..5c16bf0f324be 100644
--- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx
@@ -53,7 +53,7 @@ interface Props {
items: ErrorGroupListAPIResponse;
}
-const ErrorGroupList: React.FC = (props) => {
+function ErrorGroupList(props: Props) {
const { items } = props;
const { urlParams } = useUrlParams();
const { serviceName } = urlParams;
@@ -213,6 +213,6 @@ const ErrorGroupList: React.FC = (props) => {
sortItems={false}
/>
);
-};
+}
export { ErrorGroupList };
diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/index.tsx b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/index.tsx
index b9a28c1c1841f..fe2303d645ec9 100644
--- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/index.tsx
@@ -22,7 +22,7 @@ import { LocalUIFilters } from '../../shared/LocalUIFilters';
import { ErrorDistribution } from '../ErrorGroupDetails/Distribution';
import { ErrorGroupList } from './List';
-const ErrorGroupOverview: React.FC = () => {
+function ErrorGroupOverview() {
const { urlParams, uiFilters } = useUrlParams();
const { serviceName, start, end, sortField, sortDirection } = urlParams;
@@ -123,6 +123,6 @@ const ErrorGroupOverview: React.FC = () => {
>
);
-};
+}
export { ErrorGroupOverview };
diff --git a/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.test.tsx b/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.test.tsx
index 6aec6e9bf181a..2c19356a7fd52 100644
--- a/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.test.tsx
+++ b/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.test.tsx
@@ -16,6 +16,7 @@ import {
} from '../../../context/ApmPluginContext/MockApmPluginContext';
const setBreadcrumbs = jest.fn();
+const changeTitle = jest.fn();
function mountBreadcrumb(route: string, params = '') {
mount(
@@ -27,6 +28,7 @@ function mountBreadcrumb(route: string, params = '') {
...mockApmPluginContextValue.core,
chrome: {
...mockApmPluginContextValue.core.chrome,
+ docTitle: { change: changeTitle },
setBreadcrumbs,
},
},
@@ -42,23 +44,14 @@ function mountBreadcrumb(route: string, params = '') {
}
describe('UpdateBreadcrumbs', () => {
- let realDoc: Document;
-
beforeEach(() => {
- realDoc = window.document;
- (window.document as any) = {
- title: 'Kibana',
- };
setBreadcrumbs.mockReset();
+ changeTitle.mockReset();
});
- afterEach(() => {
- (window.document as any) = realDoc;
- });
-
- it('Homepage', () => {
+ it('Changes the homepage title', () => {
mountBreadcrumb('/');
- expect(window.document.title).toMatchInlineSnapshot(`"APM"`);
+ expect(changeTitle).toHaveBeenCalledWith(['APM']);
});
it('/services/:serviceName/errors/:groupId', () => {
@@ -90,9 +83,13 @@ describe('UpdateBreadcrumbs', () => {
},
{ text: 'myGroupId', href: undefined },
]);
- expect(window.document.title).toMatchInlineSnapshot(
- `"myGroupId | Errors | opbeans-node | Services | APM"`
- );
+ expect(changeTitle).toHaveBeenCalledWith([
+ 'myGroupId',
+ 'Errors',
+ 'opbeans-node',
+ 'Services',
+ 'APM',
+ ]);
});
it('/services/:serviceName/errors', () => {
@@ -104,9 +101,12 @@ describe('UpdateBreadcrumbs', () => {
{ text: 'opbeans-node', href: '#/services/opbeans-node?kuery=myKuery' },
{ text: 'Errors', href: undefined },
]);
- expect(window.document.title).toMatchInlineSnapshot(
- `"Errors | opbeans-node | Services | APM"`
- );
+ expect(changeTitle).toHaveBeenCalledWith([
+ 'Errors',
+ 'opbeans-node',
+ 'Services',
+ 'APM',
+ ]);
});
it('/services/:serviceName/transactions', () => {
@@ -118,9 +118,12 @@ describe('UpdateBreadcrumbs', () => {
{ text: 'opbeans-node', href: '#/services/opbeans-node?kuery=myKuery' },
{ text: 'Transactions', href: undefined },
]);
- expect(window.document.title).toMatchInlineSnapshot(
- `"Transactions | opbeans-node | Services | APM"`
- );
+ expect(changeTitle).toHaveBeenCalledWith([
+ 'Transactions',
+ 'opbeans-node',
+ 'Services',
+ 'APM',
+ ]);
});
it('/services/:serviceName/transactions/view?transactionName=my-transaction-name', () => {
@@ -139,8 +142,12 @@ describe('UpdateBreadcrumbs', () => {
},
{ text: 'my-transaction-name', href: undefined },
]);
- expect(window.document.title).toMatchInlineSnapshot(
- `"my-transaction-name | Transactions | opbeans-node | Services | APM"`
- );
+ expect(changeTitle).toHaveBeenCalledWith([
+ 'my-transaction-name',
+ 'Transactions',
+ 'opbeans-node',
+ 'Services',
+ 'APM',
+ ]);
});
});
diff --git a/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.tsx b/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.tsx
index 7a27eae6e89f7..e7657c63f41bb 100644
--- a/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.tsx
+++ b/x-pack/plugins/apm/public/components/app/Main/UpdateBreadcrumbs.tsx
@@ -22,10 +22,7 @@ interface Props {
}
function getTitleFromBreadCrumbs(breadcrumbs: Breadcrumb[]) {
- return breadcrumbs
- .map(({ value }) => value)
- .reverse()
- .join(' | ');
+ return breadcrumbs.map(({ value }) => value).reverse();
}
class UpdateBreadcrumbsComponent extends React.Component {
@@ -43,7 +40,9 @@ class UpdateBreadcrumbsComponent extends React.Component {
}
);
- document.title = getTitleFromBreadCrumbs(this.props.breadcrumbs);
+ this.props.core.chrome.docTitle.change(
+ getTitleFromBreadCrumbs(this.props.breadcrumbs)
+ );
this.props.core.chrome.setBreadcrumbs(breadcrumbs);
}
diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/Breakdowns/BreakdownFilter.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/Breakdowns/BreakdownFilter.tsx
index 332cf40a465f9..7e5e7cdc53c55 100644
--- a/x-pack/plugins/apm/public/components/app/RumDashboard/Breakdowns/BreakdownFilter.tsx
+++ b/x-pack/plugins/apm/public/components/app/RumDashboard/Breakdowns/BreakdownFilter.tsx
@@ -20,11 +20,11 @@ interface Props {
onBreakdownChange: (values: BreakdownItem[]) => void;
}
-export const BreakdownFilter = ({
+export function BreakdownFilter({
id,
selectedBreakdowns,
onBreakdownChange,
-}: Props) => {
+}: Props) {
const categories: BreakdownItem[] = [
{
name: 'Browser',
@@ -65,4 +65,4 @@ export const BreakdownFilter = ({
}}
/>
);
-};
+}
diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/Breakdowns/BreakdownGroup.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/Breakdowns/BreakdownGroup.tsx
index 5bf84b6c918c5..d4f80667ce98b 100644
--- a/x-pack/plugins/apm/public/components/app/RumDashboard/Breakdowns/BreakdownGroup.tsx
+++ b/x-pack/plugins/apm/public/components/app/RumDashboard/Breakdowns/BreakdownGroup.tsx
@@ -22,12 +22,12 @@ export interface BreakdownGroupProps {
onChange: (values: BreakdownItem[]) => void;
}
-export const BreakdownGroup = ({
+export function BreakdownGroup({
id,
disabled,
onChange,
items,
-}: BreakdownGroupProps) => {
+}: BreakdownGroupProps) {
const [isOpen, setIsOpen] = useState(false);
const [activeItems, setActiveItems] = useState(items);
@@ -97,4 +97,4 @@ export const BreakdownGroup = ({
);
-};
+}
diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ChartWrapper/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ChartWrapper/index.tsx
index a3cfbb28abee2..970365779a0a2 100644
--- a/x-pack/plugins/apm/public/components/app/RumDashboard/ChartWrapper/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ChartWrapper/index.tsx
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { FC, HTMLAttributes } from 'react';
+import React, { HTMLAttributes, ReactNode } from 'react';
import {
EuiErrorBoundary,
EuiFlexGroup,
@@ -13,6 +13,7 @@ import {
} from '@elastic/eui';
interface Props {
+ children?: ReactNode;
/**
* Height for the chart
*/
@@ -27,12 +28,12 @@ interface Props {
'aria-label'?: string;
}
-export const ChartWrapper: FC = ({
+export function ChartWrapper({
loading = false,
height = '100%',
children,
...rest
-}) => {
+}: Props) {
const opacity = loading === true ? 0.3 : 1;
return (
@@ -60,4 +61,4 @@ export const ChartWrapper: FC = ({
)}
);
-};
+}
diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/PageLoadDistChart.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/PageLoadDistChart.tsx
index 6c5b539fcecfa..b2b5e66d06ac6 100644
--- a/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/PageLoadDistChart.tsx
+++ b/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/PageLoadDistChart.tsx
@@ -70,6 +70,7 @@ export function PageLoadDistChart({
onPercentileChange(minX, maxX);
};
+ // eslint-disable-next-line react/function-component-definition
const headerFormatter: TooltipValueFormatter = (tooltip: TooltipValue) => {
return (
-
>
);
diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/list_page/components/create_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/list_page/components/create_config.tsx
index fc593705a4e1b..749716b473c85 100644
--- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/list_page/components/create_config.tsx
+++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/list_page/components/create_config.tsx
@@ -160,7 +160,7 @@ export const CreateAgentConfigFlyout: React.FunctionComponent = ({
);
return (
-
+ onClose()} size="l" maxWidth={400} {...restOfProps}>
{header}
{body}
{footer}
diff --git a/x-pack/plugins/ingest_manager/server/services/agent_config.ts b/x-pack/plugins/ingest_manager/server/services/agent_config.ts
index 0a9adc1f1c593..3886146e28806 100644
--- a/x-pack/plugins/ingest_manager/server/services/agent_config.ts
+++ b/x-pack/plugins/ingest_manager/server/services/agent_config.ts
@@ -233,16 +233,14 @@ class AgentConfigService {
if (baseAgentConfig.package_configs.length) {
const newPackageConfigs = (baseAgentConfig.package_configs as PackageConfig[]).map(
(packageConfig: PackageConfig) => {
- const { id: packageConfigId, ...newPackageConfig } = packageConfig;
+ const { id: packageConfigId, version, ...newPackageConfig } = packageConfig;
return newPackageConfig;
}
);
- await packageConfigService.bulkCreate(
- soClient,
- newPackageConfigs,
- newAgentConfig.id,
- options
- );
+ await packageConfigService.bulkCreate(soClient, newPackageConfigs, newAgentConfig.id, {
+ ...options,
+ bumpConfigRevision: false,
+ });
}
// Get updated config
diff --git a/x-pack/plugins/ingest_manager/server/services/package_config.ts b/x-pack/plugins/ingest_manager/server/services/package_config.ts
index c2d465cf7c73f..5d1c5d1717714 100644
--- a/x-pack/plugins/ingest_manager/server/services/package_config.ts
+++ b/x-pack/plugins/ingest_manager/server/services/package_config.ts
@@ -121,7 +121,7 @@ class PackageConfigService {
options?: { user?: AuthenticatedUser; bumpConfigRevision?: boolean }
): Promise {
const isoDate = new Date().toISOString();
- const { saved_objects: newSos } = await soClient.bulkCreate(
+ const { saved_objects } = await soClient.bulkCreate(
packageConfigs.map((packageConfig) => ({
type: SAVED_OBJECT_TYPE,
attributes: {
@@ -136,6 +136,9 @@ class PackageConfigService {
}))
);
+ // Filter out invalid SOs
+ const newSos = saved_objects.filter((so) => !so.error && so.attributes);
+
// Assign it to the given agent config
await agentConfigService.assignPackageConfigs(
soClient,
diff --git a/x-pack/plugins/lists/common/constants.mock.ts b/x-pack/plugins/lists/common/constants.mock.ts
index 30f219c3ec101..22706890e2020 100644
--- a/x-pack/plugins/lists/common/constants.mock.ts
+++ b/x-pack/plugins/lists/common/constants.mock.ts
@@ -6,6 +6,7 @@
import { EntriesArray } from './schemas/types';
export const DATE_NOW = '2020-04-20T15:25:31.830Z';
+export const OLD_DATE_RELATIVE_TO_DATE_NOW = '2020-04-19T15:25:31.830Z';
export const USER = 'some user';
export const LIST_INDEX = '.lists';
export const LIST_ITEM_INDEX = '.items';
diff --git a/x-pack/plugins/lists/common/schemas/request/create_endpoint_list_item_schema.test.ts b/x-pack/plugins/lists/common/schemas/request/create_endpoint_list_item_schema.test.ts
index 5de9fbb0d5b50..75e0410be610a 100644
--- a/x-pack/plugins/lists/common/schemas/request/create_endpoint_list_item_schema.test.ts
+++ b/x-pack/plugins/lists/common/schemas/request/create_endpoint_list_item_schema.test.ts
@@ -8,8 +8,8 @@ import { left } from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/pipeable';
import { exactCheck, foldLeftRight, getPaths } from '../../siem_common_deps';
-import { getCreateCommentsArrayMock } from '../types/create_comments.mock';
-import { getCommentsMock } from '../types/comments.mock';
+import { getCreateCommentsArrayMock } from '../types/create_comment.mock';
+import { getCommentsMock } from '../types/comment.mock';
import { CommentsArray } from '../types';
import {
@@ -19,7 +19,7 @@ import {
import { getCreateEndpointListItemSchemaMock } from './create_endpoint_list_item_schema.mock';
describe('create_endpoint_list_item_schema', () => {
- test('it should validate a typical list item request not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied a typical list item request not counting the auto generated uuid', () => {
const payload = getCreateEndpointListItemSchemaMock();
const decoded = createEndpointListItemSchema.decode(payload);
const checked = exactCheck(payload, decoded);
@@ -29,7 +29,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual(payload);
});
- test('it should not validate an undefined for "description"', () => {
+ test('it should fail validation when supplied an undefined for "description"', () => {
const payload = getCreateEndpointListItemSchemaMock();
delete payload.description;
const decoded = createEndpointListItemSchema.decode(payload);
@@ -41,7 +41,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate an undefined for "name"', () => {
+ test('it should fail validation when supplied an undefined for "name"', () => {
const payload = getCreateEndpointListItemSchemaMock();
delete payload.name;
const decoded = createEndpointListItemSchema.decode(payload);
@@ -53,7 +53,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate an undefined for "type"', () => {
+ test('it should fail validation when supplied an undefined for "type"', () => {
const payload = getCreateEndpointListItemSchemaMock();
delete payload.type;
const decoded = createEndpointListItemSchema.decode(payload);
@@ -65,7 +65,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate a "list_id" since it does not required one', () => {
+ test('it should fail validation when supplied a "list_id" since it does not required one', () => {
const inputPayload: CreateEndpointListItemSchema & { list_id: string } = {
...getCreateEndpointListItemSchemaMock(),
list_id: 'list-123',
@@ -77,7 +77,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate a "namespace_type" since it does not required one', () => {
+ test('it should fail validation when supplied a "namespace_type" since it does not required one', () => {
const inputPayload: CreateEndpointListItemSchema & { namespace_type: string } = {
...getCreateEndpointListItemSchemaMock(),
namespace_type: 'single',
@@ -89,7 +89,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should validate an undefined for "meta" but strip it out and generate a correct body not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied an undefined for "meta" but strip it out and generate a correct body not counting the auto generated uuid', () => {
const payload = getCreateEndpointListItemSchemaMock();
const outputPayload = getCreateEndpointListItemSchemaMock();
delete payload.meta;
@@ -102,7 +102,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual(outputPayload);
});
- test('it should validate an undefined for "comments" but return an array and generate a correct body not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied an undefined for "comments" but return an array and generate a correct body not counting the auto generated uuid', () => {
const inputPayload = getCreateEndpointListItemSchemaMock();
const outputPayload = getCreateEndpointListItemSchemaMock();
delete inputPayload.comments;
@@ -115,7 +115,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual(outputPayload);
});
- test('it should validate "comments" array', () => {
+ test('it should pass validation when supplied "comments" array', () => {
const inputPayload = {
...getCreateEndpointListItemSchemaMock(),
comments: getCreateCommentsArrayMock(),
@@ -128,7 +128,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual(inputPayload);
});
- test('it should NOT validate "comments" with "created_at" or "created_by" values', () => {
+ test('it should fail validation when supplied "comments" with "created_at", "created_by", or "id" values', () => {
const inputPayload: Omit & {
comments?: CommentsArray;
} = {
@@ -138,11 +138,11 @@ describe('create_endpoint_list_item_schema', () => {
const decoded = createEndpointListItemSchema.decode(inputPayload);
const checked = exactCheck(inputPayload, decoded);
const message = pipe(checked, foldLeftRight);
- expect(getPaths(left(message.errors))).toEqual(['invalid keys "created_at,created_by"']);
+ expect(getPaths(left(message.errors))).toEqual(['invalid keys "created_at,created_by,id"']);
expect(message.schema).toEqual({});
});
- test('it should NOT validate an undefined for "entries"', () => {
+ test('it should fail validation when supplied an undefined for "entries"', () => {
const inputPayload = getCreateEndpointListItemSchemaMock();
const outputPayload = getCreateEndpointListItemSchemaMock();
delete inputPayload.entries;
@@ -157,7 +157,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should validate an undefined for "tags" but return an array and generate a correct body not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied an undefined for "tags" but return an array and generate a correct body not counting the auto generated uuid', () => {
const inputPayload = getCreateEndpointListItemSchemaMock();
const outputPayload = getCreateEndpointListItemSchemaMock();
delete inputPayload.tags;
@@ -170,7 +170,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual(outputPayload);
});
- test('it should validate an undefined for "_tags" but return an array and generate a correct body not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied an undefined for "_tags" but return an array and generate a correct body not counting the auto generated uuid', () => {
const inputPayload = getCreateEndpointListItemSchemaMock();
const outputPayload = getCreateEndpointListItemSchemaMock();
delete inputPayload._tags;
@@ -183,7 +183,7 @@ describe('create_endpoint_list_item_schema', () => {
expect(message.schema).toEqual(outputPayload);
});
- test('it should validate an undefined for "item_id" and auto generate a uuid', () => {
+ test('it should pass validation when supplied an undefined for "item_id" and auto generate a uuid', () => {
const inputPayload = getCreateEndpointListItemSchemaMock();
delete inputPayload.item_id;
const decoded = createEndpointListItemSchema.decode(inputPayload);
@@ -195,7 +195,7 @@ describe('create_endpoint_list_item_schema', () => {
);
});
- test('it should validate an undefined for "item_id" and generate a correct body not counting the uuid', () => {
+ test('it should pass validation when supplied an undefined for "item_id" and generate a correct body not counting the uuid', () => {
const inputPayload = getCreateEndpointListItemSchemaMock();
delete inputPayload.item_id;
const decoded = createEndpointListItemSchema.decode(inputPayload);
diff --git a/x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.test.ts b/x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.test.ts
index 08f3966af08d9..cf4c1fea0306f 100644
--- a/x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.test.ts
+++ b/x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.test.ts
@@ -8,8 +8,8 @@ import { left } from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/pipeable';
import { exactCheck, foldLeftRight, getPaths } from '../../siem_common_deps';
-import { getCreateCommentsArrayMock } from '../types/create_comments.mock';
-import { getCommentsMock } from '../types/comments.mock';
+import { getCreateCommentsArrayMock } from '../types/create_comment.mock';
+import { getCommentsMock } from '../types/comment.mock';
import { CommentsArray } from '../types';
import {
@@ -19,7 +19,7 @@ import {
import { getCreateExceptionListItemSchemaMock } from './create_exception_list_item_schema.mock';
describe('create_exception_list_item_schema', () => {
- test('it should validate a typical exception list item request not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied a typical exception list item request not counting the auto generated uuid', () => {
const payload = getCreateExceptionListItemSchemaMock();
const decoded = createExceptionListItemSchema.decode(payload);
const checked = exactCheck(payload, decoded);
@@ -29,7 +29,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual(payload);
});
- test('it should not validate an undefined for "description"', () => {
+ test('it should fail validation when supplied an undefined for "description"', () => {
const payload = getCreateExceptionListItemSchemaMock();
delete payload.description;
const decoded = createExceptionListItemSchema.decode(payload);
@@ -41,7 +41,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate an undefined for "name"', () => {
+ test('it should fail validation when supplied an undefined for "name"', () => {
const payload = getCreateExceptionListItemSchemaMock();
delete payload.name;
const decoded = createExceptionListItemSchema.decode(payload);
@@ -53,7 +53,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate an undefined for "type"', () => {
+ test('it should fail validation when supplied an undefined for "type"', () => {
const payload = getCreateExceptionListItemSchemaMock();
delete payload.type;
const decoded = createExceptionListItemSchema.decode(payload);
@@ -65,7 +65,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate an undefined for "list_id"', () => {
+ test('it should fail validation when supplied an undefined for "list_id"', () => {
const inputPayload = getCreateExceptionListItemSchemaMock();
delete inputPayload.list_id;
const decoded = createExceptionListItemSchema.decode(inputPayload);
@@ -77,7 +77,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should validate an undefined for "meta" but strip it out and generate a correct body not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied an undefined for "meta" but strip it out and generate a correct body not counting the auto generated uuid', () => {
const payload = getCreateExceptionListItemSchemaMock();
const outputPayload = getCreateExceptionListItemSchemaMock();
delete payload.meta;
@@ -90,7 +90,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual(outputPayload);
});
- test('it should validate an undefined for "comments" but return an array and generate a correct body not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied an undefined for "comments" but return an array and generate a correct body not counting the auto generated uuid', () => {
const inputPayload = getCreateExceptionListItemSchemaMock();
const outputPayload = getCreateExceptionListItemSchemaMock();
delete inputPayload.comments;
@@ -103,7 +103,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual(outputPayload);
});
- test('it should validate "comments" array', () => {
+ test('it should pass validation when supplied "comments" array', () => {
const inputPayload = {
...getCreateExceptionListItemSchemaMock(),
comments: getCreateCommentsArrayMock(),
@@ -116,7 +116,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual(inputPayload);
});
- test('it should NOT validate "comments" with "created_at" or "created_by" values', () => {
+ test('it should fail validation when supplied "comments" with "created_at" or "created_by" values', () => {
const inputPayload: Omit & {
comments?: CommentsArray;
} = {
@@ -126,11 +126,11 @@ describe('create_exception_list_item_schema', () => {
const decoded = createExceptionListItemSchema.decode(inputPayload);
const checked = exactCheck(inputPayload, decoded);
const message = pipe(checked, foldLeftRight);
- expect(getPaths(left(message.errors))).toEqual(['invalid keys "created_at,created_by"']);
+ expect(getPaths(left(message.errors))).toEqual(['invalid keys "created_at,created_by,id"']);
expect(message.schema).toEqual({});
});
- test('it should NOT validate an undefined for "entries"', () => {
+ test('it should fail validation when supplied an undefined for "entries"', () => {
const inputPayload = getCreateExceptionListItemSchemaMock();
const outputPayload = getCreateExceptionListItemSchemaMock();
delete inputPayload.entries;
@@ -145,7 +145,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual({});
});
- test('it should validate an undefined for "namespace_type" but return enum "single" and generate a correct body not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied an undefined for "namespace_type" but return enum "single" and generate a correct body not counting the auto generated uuid', () => {
const inputPayload = getCreateExceptionListItemSchemaMock();
const outputPayload = getCreateExceptionListItemSchemaMock();
delete inputPayload.namespace_type;
@@ -158,7 +158,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual(outputPayload);
});
- test('it should validate an undefined for "tags" but return an array and generate a correct body not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied an undefined for "tags" but return an array and generate a correct body not counting the auto generated uuid', () => {
const inputPayload = getCreateExceptionListItemSchemaMock();
const outputPayload = getCreateExceptionListItemSchemaMock();
delete inputPayload.tags;
@@ -171,7 +171,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual(outputPayload);
});
- test('it should validate an undefined for "_tags" but return an array and generate a correct body not counting the auto generated uuid', () => {
+ test('it should pass validation when supplied an undefined for "_tags" but return an array and generate a correct body not counting the auto generated uuid', () => {
const inputPayload = getCreateExceptionListItemSchemaMock();
const outputPayload = getCreateExceptionListItemSchemaMock();
delete inputPayload._tags;
@@ -184,7 +184,7 @@ describe('create_exception_list_item_schema', () => {
expect(message.schema).toEqual(outputPayload);
});
- test('it should validate an undefined for "item_id" and auto generate a uuid', () => {
+ test('it should pass validation when supplied an undefined for "item_id" and auto generate a uuid', () => {
const inputPayload = getCreateExceptionListItemSchemaMock();
delete inputPayload.item_id;
const decoded = createExceptionListItemSchema.decode(inputPayload);
@@ -196,7 +196,7 @@ describe('create_exception_list_item_schema', () => {
);
});
- test('it should validate an undefined for "item_id" and generate a correct body not counting the uuid', () => {
+ test('it should pass validation when supplied an undefined for "item_id" and generate a correct body not counting the uuid', () => {
const inputPayload = getCreateExceptionListItemSchemaMock();
delete inputPayload.item_id;
const decoded = createExceptionListItemSchema.decode(inputPayload);
diff --git a/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_validation.test.ts b/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_validation.test.ts
new file mode 100644
index 0000000000000..3358582786cc7
--- /dev/null
+++ b/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_validation.test.ts
@@ -0,0 +1,43 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { getUpdateExceptionListItemSchemaMock } from './update_exception_list_item_schema.mock';
+import { validateComments } from './update_exception_list_item_validation';
+
+describe('update_exception_list_item_validation', () => {
+ describe('#validateComments', () => {
+ test('it returns no errors if comments is undefined', () => {
+ const payload = getUpdateExceptionListItemSchemaMock();
+ delete payload.comments;
+ const output = validateComments(payload);
+
+ expect(output).toEqual([]);
+ });
+
+ test('it returns no errors if new comments are append only', () => {
+ const payload = getUpdateExceptionListItemSchemaMock();
+ payload.comments = [
+ { comment: 'Im an old comment', id: '1' },
+ { comment: 'Im a new comment' },
+ ];
+ const output = validateComments(payload);
+
+ expect(output).toEqual([]);
+ });
+
+ test('it returns error if comments are not append only', () => {
+ const payload = getUpdateExceptionListItemSchemaMock();
+ payload.comments = [
+ { comment: 'Im an old comment', id: '1' },
+ { comment: 'Im a new comment modifying the order of existing comments' },
+ { comment: 'Im an old comment', id: '2' },
+ ];
+ const output = validateComments(payload);
+
+ expect(output).toEqual(['item "comments" are append only']);
+ });
+ });
+});
diff --git a/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_validation.ts b/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_validation.ts
new file mode 100644
index 0000000000000..5e44c4e9f73e7
--- /dev/null
+++ b/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_validation.ts
@@ -0,0 +1,40 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { UpdateExceptionListItemSchema } from './update_exception_list_item_schema';
+
+export const validateComments = (item: UpdateExceptionListItemSchema): string[] => {
+ if (item.comments == null) {
+ return [];
+ }
+
+ const [appendOnly] = item.comments.reduce(
+ (acc, comment) => {
+ const [, hasNewComments] = acc;
+ if (comment.id == null) {
+ return [true, true];
+ }
+
+ if (hasNewComments && comment.id != null) {
+ return [false, true];
+ }
+
+ return acc;
+ },
+ [true, false]
+ );
+ if (!appendOnly) {
+ return ['item "comments" are append only'];
+ } else {
+ return [];
+ }
+};
+
+export const updateExceptionListItemValidate = (
+ schema: UpdateExceptionListItemSchema
+): string[] => {
+ return [...validateComments(schema)];
+};
diff --git a/x-pack/plugins/lists/common/schemas/types/comments.mock.ts b/x-pack/plugins/lists/common/schemas/types/comment.mock.ts
similarity index 71%
rename from x-pack/plugins/lists/common/schemas/types/comments.mock.ts
rename to x-pack/plugins/lists/common/schemas/types/comment.mock.ts
index 9e56ac292f8b5..213259b3cce29 100644
--- a/x-pack/plugins/lists/common/schemas/types/comments.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/types/comment.mock.ts
@@ -4,14 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { DATE_NOW, USER } from '../../constants.mock';
+import { DATE_NOW, ID, USER } from '../../constants.mock';
-import { Comments, CommentsArray } from './comments';
+import { Comment, CommentsArray } from './comment';
-export const getCommentsMock = (): Comments => ({
+export const getCommentsMock = (): Comment => ({
comment: 'some old comment',
created_at: DATE_NOW,
created_by: USER,
+ id: ID,
});
export const getCommentsArrayMock = (): CommentsArray => [getCommentsMock(), getCommentsMock()];
diff --git a/x-pack/plugins/lists/common/schemas/types/comments.test.ts b/x-pack/plugins/lists/common/schemas/types/comment.test.ts
similarity index 56%
rename from x-pack/plugins/lists/common/schemas/types/comments.test.ts
rename to x-pack/plugins/lists/common/schemas/types/comment.test.ts
index 29bfde03abcc8..c7c945277f756 100644
--- a/x-pack/plugins/lists/common/schemas/types/comments.test.ts
+++ b/x-pack/plugins/lists/common/schemas/types/comment.test.ts
@@ -10,56 +10,79 @@ import { left } from 'fp-ts/lib/Either';
import { DATE_NOW } from '../../constants.mock';
import { foldLeftRight, getPaths } from '../../siem_common_deps';
-import { getCommentsArrayMock, getCommentsMock } from './comments.mock';
+import { getCommentsArrayMock, getCommentsMock } from './comment.mock';
import {
- Comments,
+ Comment,
CommentsArray,
CommentsArrayOrUndefined,
- comments,
+ comment,
commentsArray,
commentsArrayOrUndefined,
-} from './comments';
+} from './comment';
-describe('Comments', () => {
- describe('comments', () => {
- test('it should validate a comments', () => {
+describe('Comment', () => {
+ describe('comment', () => {
+ test('it fails validation when "id" is undefined', () => {
+ const payload = { ...getCommentsMock(), id: undefined };
+ const decoded = comment.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([
+ 'Invalid value "undefined" supplied to "id"',
+ ]);
+ expect(message.schema).toEqual({});
+ });
+
+ test('it passes validation with a typical comment', () => {
const payload = getCommentsMock();
- const decoded = comments.decode(payload);
+ const decoded = comment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
expect(message.schema).toEqual(payload);
});
- test('it should validate with "updated_at" and "updated_by"', () => {
+ test('it passes validation with "updated_at" and "updated_by" fields included', () => {
const payload = getCommentsMock();
payload.updated_at = DATE_NOW;
payload.updated_by = 'someone';
- const decoded = comments.decode(payload);
+ const decoded = comment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
expect(message.schema).toEqual(payload);
});
- test('it should not validate when undefined', () => {
+ test('it fails validation when undefined', () => {
const payload = undefined;
- const decoded = comments.decode(payload);
+ const decoded = comment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "undefined" supplied to "({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)"',
- 'Invalid value "undefined" supplied to "({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)"',
+ 'Invalid value "undefined" supplied to "({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)"',
+ 'Invalid value "undefined" supplied to "({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)"',
]);
expect(message.schema).toEqual({});
});
- test('it should not validate when "comment" is not a string', () => {
- const payload: Omit & { comment: string[] } = {
+ test('it fails validation when "comment" is an empty string', () => {
+ const payload: Omit & { comment: string } = {
+ ...getCommentsMock(),
+ comment: '',
+ };
+ const decoded = comment.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "comment"']);
+ expect(message.schema).toEqual({});
+ });
+
+ test('it fails validation when "comment" is not a string', () => {
+ const payload: Omit & { comment: string[] } = {
...getCommentsMock(),
comment: ['some value'],
};
- const decoded = comments.decode(payload);
+ const decoded = comment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
@@ -68,12 +91,12 @@ describe('Comments', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate when "created_at" is not a string', () => {
- const payload: Omit & { created_at: number } = {
+ test('it fails validation when "created_at" is not a string', () => {
+ const payload: Omit & { created_at: number } = {
...getCommentsMock(),
created_at: 1,
};
- const decoded = comments.decode(payload);
+ const decoded = comment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
@@ -82,12 +105,12 @@ describe('Comments', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate when "created_by" is not a string', () => {
- const payload: Omit & { created_by: number } = {
+ test('it fails validation when "created_by" is not a string', () => {
+ const payload: Omit & { created_by: number } = {
...getCommentsMock(),
created_by: 1,
};
- const decoded = comments.decode(payload);
+ const decoded = comment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
@@ -96,12 +119,12 @@ describe('Comments', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate when "updated_at" is not a string', () => {
- const payload: Omit & { updated_at: number } = {
+ test('it fails validation when "updated_at" is not a string', () => {
+ const payload: Omit & { updated_at: number } = {
...getCommentsMock(),
updated_at: 1,
};
- const decoded = comments.decode(payload);
+ const decoded = comment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
@@ -110,12 +133,12 @@ describe('Comments', () => {
expect(message.schema).toEqual({});
});
- test('it should not validate when "updated_by" is not a string', () => {
- const payload: Omit & { updated_by: number } = {
+ test('it fails validation when "updated_by" is not a string', () => {
+ const payload: Omit & { updated_by: number } = {
...getCommentsMock(),
updated_by: 1,
};
- const decoded = comments.decode(payload);
+ const decoded = comment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
@@ -125,11 +148,11 @@ describe('Comments', () => {
});
test('it should strip out extra keys', () => {
- const payload: Comments & {
+ const payload: Comment & {
extraKey?: string;
} = getCommentsMock();
payload.extraKey = 'some value';
- const decoded = comments.decode(payload);
+ const decoded = comment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
@@ -138,7 +161,7 @@ describe('Comments', () => {
});
describe('commentsArray', () => {
- test('it should validate an array of comments', () => {
+ test('it passes validation an array of Comment', () => {
const payload = getCommentsArrayMock();
const decoded = commentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -147,7 +170,7 @@ describe('Comments', () => {
expect(message.schema).toEqual(payload);
});
- test('it should validate when a comments includes "updated_at" and "updated_by"', () => {
+ test('it passes validation when a Comment includes "updated_at" and "updated_by"', () => {
const commentsPayload = getCommentsMock();
commentsPayload.updated_at = DATE_NOW;
commentsPayload.updated_by = 'someone';
@@ -159,32 +182,32 @@ describe('Comments', () => {
expect(message.schema).toEqual(payload);
});
- test('it should not validate when undefined', () => {
+ test('it fails validation when undefined', () => {
const payload = undefined;
const decoded = commentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "undefined" supplied to "Array<({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
+ 'Invalid value "undefined" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
]);
expect(message.schema).toEqual({});
});
- test('it should not validate when array includes non comments types', () => {
+ test('it fails validation when array includes non Comment types', () => {
const payload = ([1] as unknown) as CommentsArray;
const decoded = commentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "1" supplied to "Array<({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
- 'Invalid value "1" supplied to "Array<({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
]);
expect(message.schema).toEqual({});
});
});
describe('commentsArrayOrUndefined', () => {
- test('it should validate an array of comments', () => {
+ test('it passes validation an array of Comment', () => {
const payload = getCommentsArrayMock();
const decoded = commentsArrayOrUndefined.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -193,7 +216,7 @@ describe('Comments', () => {
expect(message.schema).toEqual(payload);
});
- test('it should validate when undefined', () => {
+ test('it passes validation when undefined', () => {
const payload = undefined;
const decoded = commentsArrayOrUndefined.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -202,14 +225,14 @@ describe('Comments', () => {
expect(message.schema).toEqual(payload);
});
- test('it should not validate when array includes non comments types', () => {
+ test('it fails validation when array includes non Comment types', () => {
const payload = ([1] as unknown) as CommentsArrayOrUndefined;
const decoded = commentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "1" supplied to "Array<({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
- 'Invalid value "1" supplied to "Array<({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
]);
expect(message.schema).toEqual({});
});
diff --git a/x-pack/plugins/lists/common/schemas/types/comments.ts b/x-pack/plugins/lists/common/schemas/types/comment.ts
similarity index 56%
rename from x-pack/plugins/lists/common/schemas/types/comments.ts
rename to x-pack/plugins/lists/common/schemas/types/comment.ts
index 0ee3b05c8102f..6b0b0166b9ee1 100644
--- a/x-pack/plugins/lists/common/schemas/types/comments.ts
+++ b/x-pack/plugins/lists/common/schemas/types/comment.ts
@@ -3,26 +3,33 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
+
+/* eslint-disable @typescript-eslint/camelcase */
+
import * as t from 'io-ts';
-export const comments = t.intersection([
+import { NonEmptyString } from '../../siem_common_deps';
+import { created_at, created_by, id, updated_at, updated_by } from '../common/schemas';
+
+export const comment = t.intersection([
t.exact(
t.type({
- comment: t.string,
- created_at: t.string, // TODO: Make this into an ISO Date string check,
- created_by: t.string,
+ comment: NonEmptyString,
+ created_at,
+ created_by,
+ id,
})
),
t.exact(
t.partial({
- updated_at: t.string,
- updated_by: t.string,
+ updated_at,
+ updated_by,
})
),
]);
-export const commentsArray = t.array(comments);
+export const commentsArray = t.array(comment);
export type CommentsArray = t.TypeOf;
-export type Comments = t.TypeOf;
+export type Comment = t.TypeOf;
export const commentsArrayOrUndefined = t.union([commentsArray, t.undefined]);
export type CommentsArrayOrUndefined = t.TypeOf;
diff --git a/x-pack/plugins/lists/common/schemas/types/create_comments.mock.ts b/x-pack/plugins/lists/common/schemas/types/create_comment.mock.ts
similarity index 73%
rename from x-pack/plugins/lists/common/schemas/types/create_comments.mock.ts
rename to x-pack/plugins/lists/common/schemas/types/create_comment.mock.ts
index 60a59432275ca..689d4ccdc2c2e 100644
--- a/x-pack/plugins/lists/common/schemas/types/create_comments.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/types/create_comment.mock.ts
@@ -3,9 +3,9 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import { CreateComments, CreateCommentsArray } from './create_comments';
+import { CreateComment, CreateCommentsArray } from './create_comment';
-export const getCreateCommentsMock = (): CreateComments => ({
+export const getCreateCommentsMock = (): CreateComment => ({
comment: 'some comments',
});
diff --git a/x-pack/plugins/lists/common/schemas/types/create_comments.test.ts b/x-pack/plugins/lists/common/schemas/types/create_comment.test.ts
similarity index 72%
rename from x-pack/plugins/lists/common/schemas/types/create_comments.test.ts
rename to x-pack/plugins/lists/common/schemas/types/create_comment.test.ts
index d2680750e05e4..366bf84d48bbf 100644
--- a/x-pack/plugins/lists/common/schemas/types/create_comments.test.ts
+++ b/x-pack/plugins/lists/common/schemas/types/create_comment.test.ts
@@ -9,44 +9,44 @@ import { left } from 'fp-ts/lib/Either';
import { foldLeftRight, getPaths } from '../../siem_common_deps';
-import { getCreateCommentsArrayMock, getCreateCommentsMock } from './create_comments.mock';
+import { getCreateCommentsArrayMock, getCreateCommentsMock } from './create_comment.mock';
import {
- CreateComments,
+ CreateComment,
CreateCommentsArray,
CreateCommentsArrayOrUndefined,
- createComments,
+ createComment,
createCommentsArray,
createCommentsArrayOrUndefined,
-} from './create_comments';
+} from './create_comment';
-describe('CreateComments', () => {
- describe('createComments', () => {
- test('it should validate a comments', () => {
+describe('CreateComment', () => {
+ describe('createComment', () => {
+ test('it passes validation with a default comment', () => {
const payload = getCreateCommentsMock();
- const decoded = createComments.decode(payload);
+ const decoded = createComment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
expect(message.schema).toEqual(payload);
});
- test('it should not validate when undefined', () => {
+ test('it fails validation when undefined', () => {
const payload = undefined;
- const decoded = createComments.decode(payload);
+ const decoded = createComment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "undefined" supplied to "{| comment: string |}"',
+ 'Invalid value "undefined" supplied to "{| comment: NonEmptyString |}"',
]);
expect(message.schema).toEqual({});
});
- test('it should not validate when "comment" is not a string', () => {
- const payload: Omit & { comment: string[] } = {
+ test('it fails validation when "comment" is not a string', () => {
+ const payload: Omit & { comment: string[] } = {
...getCreateCommentsMock(),
comment: ['some value'],
};
- const decoded = createComments.decode(payload);
+ const decoded = createComment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
@@ -56,11 +56,11 @@ describe('CreateComments', () => {
});
test('it should strip out extra keys', () => {
- const payload: CreateComments & {
+ const payload: CreateComment & {
extraKey?: string;
} = getCreateCommentsMock();
payload.extraKey = 'some value';
- const decoded = createComments.decode(payload);
+ const decoded = createComment.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
@@ -69,7 +69,7 @@ describe('CreateComments', () => {
});
describe('createCommentsArray', () => {
- test('it should validate an array of comments', () => {
+ test('it passes validation an array of comments', () => {
const payload = getCreateCommentsArrayMock();
const decoded = createCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -78,31 +78,31 @@ describe('CreateComments', () => {
expect(message.schema).toEqual(payload);
});
- test('it should not validate when undefined', () => {
+ test('it fails validation when undefined', () => {
const payload = undefined;
const decoded = createCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "undefined" supplied to "Array<{| comment: string |}>"',
+ 'Invalid value "undefined" supplied to "Array<{| comment: NonEmptyString |}>"',
]);
expect(message.schema).toEqual({});
});
- test('it should not validate when array includes non comments types', () => {
+ test('it fails validation when array includes non comments types', () => {
const payload = ([1] as unknown) as CreateCommentsArray;
const decoded = createCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "1" supplied to "Array<{| comment: string |}>"',
+ 'Invalid value "1" supplied to "Array<{| comment: NonEmptyString |}>"',
]);
expect(message.schema).toEqual({});
});
});
describe('createCommentsArrayOrUndefined', () => {
- test('it should validate an array of comments', () => {
+ test('it passes validation an array of comments', () => {
const payload = getCreateCommentsArrayMock();
const decoded = createCommentsArrayOrUndefined.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -111,7 +111,7 @@ describe('CreateComments', () => {
expect(message.schema).toEqual(payload);
});
- test('it should validate when undefined', () => {
+ test('it passes validation when undefined', () => {
const payload = undefined;
const decoded = createCommentsArrayOrUndefined.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -120,13 +120,13 @@ describe('CreateComments', () => {
expect(message.schema).toEqual(payload);
});
- test('it should not validate when array includes non comments types', () => {
+ test('it fails validation when array includes non comments types', () => {
const payload = ([1] as unknown) as CreateCommentsArrayOrUndefined;
const decoded = createCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "1" supplied to "Array<{| comment: string |}>"',
+ 'Invalid value "1" supplied to "Array<{| comment: NonEmptyString |}>"',
]);
expect(message.schema).toEqual({});
});
diff --git a/x-pack/plugins/lists/common/schemas/types/create_comments.ts b/x-pack/plugins/lists/common/schemas/types/create_comment.ts
similarity index 64%
rename from x-pack/plugins/lists/common/schemas/types/create_comments.ts
rename to x-pack/plugins/lists/common/schemas/types/create_comment.ts
index c34419298ef93..fd33313430ce6 100644
--- a/x-pack/plugins/lists/common/schemas/types/create_comments.ts
+++ b/x-pack/plugins/lists/common/schemas/types/create_comment.ts
@@ -5,14 +5,17 @@
*/
import * as t from 'io-ts';
-export const createComments = t.exact(
+import { NonEmptyString } from '../../siem_common_deps';
+
+export const createComment = t.exact(
t.type({
- comment: t.string,
+ comment: NonEmptyString,
})
);
-export const createCommentsArray = t.array(createComments);
+export type CreateComment = t.TypeOf;
+export const createCommentsArray = t.array(createComment);
export type CreateCommentsArray = t.TypeOf;
-export type CreateComments = t.TypeOf;
+export type CreateComments = t.TypeOf;
export const createCommentsArrayOrUndefined = t.union([createCommentsArray, t.undefined]);
export type CreateCommentsArrayOrUndefined = t.TypeOf;
diff --git a/x-pack/plugins/lists/common/schemas/types/default_comments_array.test.ts b/x-pack/plugins/lists/common/schemas/types/default_comments_array.test.ts
index 3a4241aaec82d..541b8ab1c799c 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_comments_array.test.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_comments_array.test.ts
@@ -10,11 +10,11 @@ import { left } from 'fp-ts/lib/Either';
import { foldLeftRight, getPaths } from '../../siem_common_deps';
import { DefaultCommentsArray } from './default_comments_array';
-import { CommentsArray } from './comments';
-import { getCommentsArrayMock } from './comments.mock';
+import { CommentsArray } from './comment';
+import { getCommentsArrayMock } from './comment.mock';
describe('default_comments_array', () => {
- test('it should validate an empty array', () => {
+ test('it should pass validation when supplied an empty array', () => {
const payload: CommentsArray = [];
const decoded = DefaultCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -23,7 +23,7 @@ describe('default_comments_array', () => {
expect(message.schema).toEqual(payload);
});
- test('it should validate an array of comments', () => {
+ test('it should pass validation when supplied an array of comments', () => {
const payload: CommentsArray = getCommentsArrayMock();
const decoded = DefaultCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -32,27 +32,26 @@ describe('default_comments_array', () => {
expect(message.schema).toEqual(payload);
});
- test('it should NOT validate an array of numbers', () => {
+ test('it should fail validation when supplied an array of numbers', () => {
const payload = [1];
const decoded = DefaultCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
- // TODO: Known weird error formatting that is on our list to address
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "1" supplied to "Array<({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
- 'Invalid value "1" supplied to "Array<({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
]);
expect(message.schema).toEqual({});
});
- test('it should NOT validate an array of strings', () => {
+ test('it should fail validation when supplied an array of strings', () => {
const payload = ['some string'];
const decoded = DefaultCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "some string" supplied to "Array<({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
- 'Invalid value "some string" supplied to "Array<({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
+ 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
+ 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"',
]);
expect(message.schema).toEqual({});
});
diff --git a/x-pack/plugins/lists/common/schemas/types/default_comments_array.ts b/x-pack/plugins/lists/common/schemas/types/default_comments_array.ts
index 342cf8b0d7091..0d7e28e69cf71 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_comments_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_comments_array.ts
@@ -7,7 +7,7 @@
import * as t from 'io-ts';
import { Either } from 'fp-ts/lib/Either';
-import { CommentsArray, comments } from './comments';
+import { CommentsArray, comment } from './comment';
/**
* Types the DefaultCommentsArray as:
@@ -15,8 +15,8 @@ import { CommentsArray, comments } from './comments';
*/
export const DefaultCommentsArray = new t.Type(
'DefaultCommentsArray',
- t.array(comments).is,
+ t.array(comment).is,
(input): Either =>
- input == null ? t.success([]) : t.array(comments).decode(input),
+ input == null ? t.success([]) : t.array(comment).decode(input),
t.identity
);
diff --git a/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.test.ts b/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.test.ts
index f5ef7d0ad96bd..eb960b5411904 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.test.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.test.ts
@@ -10,11 +10,12 @@ import { left } from 'fp-ts/lib/Either';
import { foldLeftRight, getPaths } from '../../siem_common_deps';
import { DefaultCreateCommentsArray } from './default_create_comments_array';
-import { CreateCommentsArray } from './create_comments';
-import { getCreateCommentsArrayMock } from './create_comments.mock';
+import { CreateCommentsArray } from './create_comment';
+import { getCreateCommentsArrayMock } from './create_comment.mock';
+import { getCommentsArrayMock } from './comment.mock';
describe('default_create_comments_array', () => {
- test('it should validate an empty array', () => {
+ test('it should pass validation when an empty array', () => {
const payload: CreateCommentsArray = [];
const decoded = DefaultCreateCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -23,7 +24,7 @@ describe('default_create_comments_array', () => {
expect(message.schema).toEqual(payload);
});
- test('it should validate an array of comments', () => {
+ test('it should pass validation when an array of comments', () => {
const payload: CreateCommentsArray = getCreateCommentsArrayMock();
const decoded = DefaultCreateCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -32,25 +33,38 @@ describe('default_create_comments_array', () => {
expect(message.schema).toEqual(payload);
});
- test('it should NOT validate an array of numbers', () => {
+ test('it should strip out "created_at" and "created_by" if they are passed in', () => {
+ const payload = getCommentsArrayMock();
+ const decoded = DefaultCreateCommentsArray.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ // TODO: Known weird error formatting that is on our list to address
+ expect(getPaths(left(message.errors))).toEqual([]);
+ expect(message.schema).toEqual([
+ { comment: 'some old comment' },
+ { comment: 'some old comment' },
+ ]);
+ });
+
+ test('it should not pass validation when an array of numbers', () => {
const payload = [1];
const decoded = DefaultCreateCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
// TODO: Known weird error formatting that is on our list to address
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "1" supplied to "Array<{| comment: string |}>"',
+ 'Invalid value "1" supplied to "Array<{| comment: NonEmptyString |}>"',
]);
expect(message.schema).toEqual({});
});
- test('it should NOT validate an array of strings', () => {
+ test('it should not pass validation when an array of strings', () => {
const payload = ['some string'];
const decoded = DefaultCreateCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "some string" supplied to "Array<{| comment: string |}>"',
+ 'Invalid value "some string" supplied to "Array<{| comment: NonEmptyString |}>"',
]);
expect(message.schema).toEqual({});
});
diff --git a/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.ts b/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.ts
index 7fd79782836e3..4df888ba728fb 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.ts
@@ -7,7 +7,7 @@
import * as t from 'io-ts';
import { Either } from 'fp-ts/lib/Either';
-import { CreateCommentsArray, createComments } from './create_comments';
+import { CreateCommentsArray, createComment } from './create_comment';
/**
* Types the DefaultCreateComments as:
@@ -19,8 +19,8 @@ export const DefaultCreateCommentsArray = new t.Type<
unknown
>(
'DefaultCreateComments',
- t.array(createComments).is,
+ t.array(createComment).is,
(input): Either =>
- input == null ? t.success([]) : t.array(createComments).decode(input),
+ input == null ? t.success([]) : t.array(createComment).decode(input),
t.identity
);
diff --git a/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.test.ts b/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.test.ts
index b023e73cb9328..612148dc4ccab 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.test.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.test.ts
@@ -10,11 +10,11 @@ import { left } from 'fp-ts/lib/Either';
import { foldLeftRight, getPaths } from '../../siem_common_deps';
import { DefaultUpdateCommentsArray } from './default_update_comments_array';
-import { UpdateCommentsArray } from './update_comments';
-import { getUpdateCommentsArrayMock } from './update_comments.mock';
+import { UpdateCommentsArray } from './update_comment';
+import { getUpdateCommentsArrayMock } from './update_comment.mock';
describe('default_update_comments_array', () => {
- test('it should validate an empty array', () => {
+ test('it should pass validation when supplied an empty array', () => {
const payload: UpdateCommentsArray = [];
const decoded = DefaultUpdateCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -23,7 +23,7 @@ describe('default_update_comments_array', () => {
expect(message.schema).toEqual(payload);
});
- test('it should validate an array of comments', () => {
+ test('it should pass validation when supplied an array of comments', () => {
const payload: UpdateCommentsArray = getUpdateCommentsArrayMock();
const decoded = DefaultUpdateCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -32,29 +32,26 @@ describe('default_update_comments_array', () => {
expect(message.schema).toEqual(payload);
});
- test('it should NOT validate an array of numbers', () => {
+ test('it should fail validation when supplied an array of numbers', () => {
const payload = [1];
const decoded = DefaultUpdateCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
- // TODO: Known weird error formatting that is on our list to address
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "1" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- 'Invalid value "1" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- 'Invalid value "1" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"',
]);
expect(message.schema).toEqual({});
});
- test('it should NOT validate an array of strings', () => {
+ test('it should fail validation when supplied an array of strings', () => {
const payload = ['some string'];
const decoded = DefaultUpdateCommentsArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "some string" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- 'Invalid value "some string" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- 'Invalid value "some string" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
+ 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"',
+ 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"',
]);
expect(message.schema).toEqual({});
});
diff --git a/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.ts b/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.ts
index 854b7cf7ada7e..35338dae64387 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.ts
@@ -7,7 +7,7 @@
import * as t from 'io-ts';
import { Either } from 'fp-ts/lib/Either';
-import { UpdateCommentsArray, updateCommentsArray } from './update_comments';
+import { UpdateCommentsArray, updateCommentsArray } from './update_comment';
/**
* Types the DefaultCommentsUpdate as:
diff --git a/x-pack/plugins/lists/common/schemas/types/index.ts b/x-pack/plugins/lists/common/schemas/types/index.ts
index 463f7cfe51ce3..6b7e9fd17a1af 100644
--- a/x-pack/plugins/lists/common/schemas/types/index.ts
+++ b/x-pack/plugins/lists/common/schemas/types/index.ts
@@ -3,9 +3,9 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-export * from './comments';
-export * from './create_comments';
-export * from './update_comments';
+export * from './comment';
+export * from './create_comment';
+export * from './update_comment';
export * from './default_comments_array';
export * from './default_create_comments_array';
export * from './default_update_comments_array';
diff --git a/x-pack/plugins/lists/common/schemas/types/update_comments.mock.ts b/x-pack/plugins/lists/common/schemas/types/update_comment.mock.ts
similarity index 54%
rename from x-pack/plugins/lists/common/schemas/types/update_comments.mock.ts
rename to x-pack/plugins/lists/common/schemas/types/update_comment.mock.ts
index 3e963c2607dc5..9b85a24abe40b 100644
--- a/x-pack/plugins/lists/common/schemas/types/update_comments.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/types/update_comment.mock.ts
@@ -4,11 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { getCommentsMock } from './comments.mock';
-import { getCreateCommentsMock } from './create_comments.mock';
-import { UpdateCommentsArray } from './update_comments';
+import { ID } from '../../constants.mock';
+
+import { UpdateComment, UpdateCommentsArray } from './update_comment';
+
+export const getUpdateCommentMock = (): UpdateComment => ({
+ comment: 'some comment',
+ id: ID,
+});
export const getUpdateCommentsArrayMock = (): UpdateCommentsArray => [
- getCommentsMock(),
- getCreateCommentsMock(),
+ getUpdateCommentMock(),
+ getUpdateCommentMock(),
];
diff --git a/x-pack/plugins/lists/common/schemas/types/update_comment.test.ts b/x-pack/plugins/lists/common/schemas/types/update_comment.test.ts
new file mode 100644
index 0000000000000..ac7716af40966
--- /dev/null
+++ b/x-pack/plugins/lists/common/schemas/types/update_comment.test.ts
@@ -0,0 +1,150 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { pipe } from 'fp-ts/lib/pipeable';
+import { left } from 'fp-ts/lib/Either';
+
+import { foldLeftRight, getPaths } from '../../siem_common_deps';
+
+import { getUpdateCommentMock, getUpdateCommentsArrayMock } from './update_comment.mock';
+import {
+ UpdateComment,
+ UpdateCommentsArray,
+ UpdateCommentsArrayOrUndefined,
+ updateComment,
+ updateCommentsArray,
+ updateCommentsArrayOrUndefined,
+} from './update_comment';
+
+describe('CommentsUpdate', () => {
+ describe('updateComment', () => {
+ test('it should pass validation when supplied typical comment update', () => {
+ const payload = getUpdateCommentMock();
+ const decoded = updateComment.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([]);
+ expect(message.schema).toEqual(payload);
+ });
+
+ test('it should fail validation when supplied an undefined for "comment"', () => {
+ const payload = getUpdateCommentMock();
+ delete payload.comment;
+ const decoded = updateComment.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([
+ 'Invalid value "undefined" supplied to "comment"',
+ ]);
+ expect(message.schema).toEqual({});
+ });
+
+ test('it should fail validation when supplied an empty string for "comment"', () => {
+ const payload = { ...getUpdateCommentMock(), comment: '' };
+ const decoded = updateComment.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "comment"']);
+ expect(message.schema).toEqual({});
+ });
+
+ test('it should pass validation when supplied an undefined for "id"', () => {
+ const payload = getUpdateCommentMock();
+ delete payload.id;
+ const decoded = updateComment.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([]);
+ expect(message.schema).toEqual(payload);
+ });
+
+ test('it should fail validation when supplied an empty string for "id"', () => {
+ const payload = { ...getUpdateCommentMock(), id: '' };
+ const decoded = updateComment.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual(['Invalid value "" supplied to "id"']);
+ expect(message.schema).toEqual({});
+ });
+
+ test('it should strip out extra key passed in', () => {
+ const payload: UpdateComment & {
+ extraKey?: string;
+ } = { ...getUpdateCommentMock(), extraKey: 'some new value' };
+ const decoded = updateComment.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([]);
+ expect(message.schema).toEqual(getUpdateCommentMock());
+ });
+ });
+
+ describe('updateCommentsArray', () => {
+ test('it should pass validation when supplied an array of comments', () => {
+ const payload = getUpdateCommentsArrayMock();
+ const decoded = updateCommentsArray.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([]);
+ expect(message.schema).toEqual(payload);
+ });
+
+ test('it should fail validation when undefined', () => {
+ const payload = undefined;
+ const decoded = updateCommentsArray.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([
+ 'Invalid value "undefined" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"',
+ ]);
+ expect(message.schema).toEqual({});
+ });
+
+ test('it should fail validation when array includes non comments types', () => {
+ const payload = ([1] as unknown) as UpdateCommentsArray;
+ const decoded = updateCommentsArray.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"',
+ ]);
+ expect(message.schema).toEqual({});
+ });
+ });
+
+ describe('updateCommentsArrayOrUndefined', () => {
+ test('it should pass validation when supplied an array of comments', () => {
+ const payload = getUpdateCommentsArrayMock();
+ const decoded = updateCommentsArrayOrUndefined.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([]);
+ expect(message.schema).toEqual(payload);
+ });
+
+ test('it should pass validation when supplied when undefined', () => {
+ const payload = undefined;
+ const decoded = updateCommentsArrayOrUndefined.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([]);
+ expect(message.schema).toEqual(payload);
+ });
+
+ test('it should fail validation when array includes non comments types', () => {
+ const payload = ([1] as unknown) as UpdateCommentsArrayOrUndefined;
+ const decoded = updateCommentsArray.decode(payload);
+ const message = pipe(decoded, foldLeftRight);
+
+ expect(getPaths(left(message.errors))).toEqual([
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"',
+ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"',
+ ]);
+ expect(message.schema).toEqual({});
+ });
+ });
+});
diff --git a/x-pack/plugins/lists/common/schemas/types/update_comments.ts b/x-pack/plugins/lists/common/schemas/types/update_comment.ts
similarity index 58%
rename from x-pack/plugins/lists/common/schemas/types/update_comments.ts
rename to x-pack/plugins/lists/common/schemas/types/update_comment.ts
index 4a21bfa363d45..b95812cb35bf9 100644
--- a/x-pack/plugins/lists/common/schemas/types/update_comments.ts
+++ b/x-pack/plugins/lists/common/schemas/types/update_comment.ts
@@ -5,10 +5,24 @@
*/
import * as t from 'io-ts';
-import { comments } from './comments';
-import { createComments } from './create_comments';
+import { NonEmptyString } from '../../siem_common_deps';
+import { id } from '../common/schemas';
-export const updateCommentsArray = t.array(t.union([comments, createComments]));
+export const updateComment = t.intersection([
+ t.exact(
+ t.type({
+ comment: NonEmptyString,
+ })
+ ),
+ t.exact(
+ t.partial({
+ id,
+ })
+ ),
+]);
+
+export type UpdateComment = t.TypeOf;
+export const updateCommentsArray = t.array(updateComment);
export type UpdateCommentsArray = t.TypeOf;
export const updateCommentsArrayOrUndefined = t.union([updateCommentsArray, t.undefined]);
export type UpdateCommentsArrayOrUndefined = t.TypeOf;
diff --git a/x-pack/plugins/lists/common/schemas/types/update_comments.test.ts b/x-pack/plugins/lists/common/schemas/types/update_comments.test.ts
deleted file mode 100644
index 7668504b031b5..0000000000000
--- a/x-pack/plugins/lists/common/schemas/types/update_comments.test.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { pipe } from 'fp-ts/lib/pipeable';
-import { left } from 'fp-ts/lib/Either';
-
-import { foldLeftRight, getPaths } from '../../siem_common_deps';
-
-import { getUpdateCommentsArrayMock } from './update_comments.mock';
-import {
- UpdateCommentsArray,
- UpdateCommentsArrayOrUndefined,
- updateCommentsArray,
- updateCommentsArrayOrUndefined,
-} from './update_comments';
-import { getCommentsMock } from './comments.mock';
-import { getCreateCommentsMock } from './create_comments.mock';
-
-describe('CommentsUpdate', () => {
- describe('updateCommentsArray', () => {
- test('it should validate an array of comments', () => {
- const payload = getUpdateCommentsArrayMock();
- const decoded = updateCommentsArray.decode(payload);
- const message = pipe(decoded, foldLeftRight);
-
- expect(getPaths(left(message.errors))).toEqual([]);
- expect(message.schema).toEqual(payload);
- });
-
- test('it should validate an array of existing comments', () => {
- const payload = [getCommentsMock()];
- const decoded = updateCommentsArray.decode(payload);
- const message = pipe(decoded, foldLeftRight);
-
- expect(getPaths(left(message.errors))).toEqual([]);
- expect(message.schema).toEqual(payload);
- });
-
- test('it should validate an array of new comments', () => {
- const payload = [getCreateCommentsMock()];
- const decoded = updateCommentsArray.decode(payload);
- const message = pipe(decoded, foldLeftRight);
-
- expect(getPaths(left(message.errors))).toEqual([]);
- expect(message.schema).toEqual(payload);
- });
-
- test('it should not validate when undefined', () => {
- const payload = undefined;
- const decoded = updateCommentsArray.decode(payload);
- const message = pipe(decoded, foldLeftRight);
-
- expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "undefined" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- ]);
- expect(message.schema).toEqual({});
- });
-
- test('it should not validate when array includes non comments types', () => {
- const payload = ([1] as unknown) as UpdateCommentsArray;
- const decoded = updateCommentsArray.decode(payload);
- const message = pipe(decoded, foldLeftRight);
-
- expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "1" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- 'Invalid value "1" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- 'Invalid value "1" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- ]);
- expect(message.schema).toEqual({});
- });
- });
-
- describe('updateCommentsArrayOrUndefined', () => {
- test('it should validate an array of comments', () => {
- const payload = getUpdateCommentsArrayMock();
- const decoded = updateCommentsArrayOrUndefined.decode(payload);
- const message = pipe(decoded, foldLeftRight);
-
- expect(getPaths(left(message.errors))).toEqual([]);
- expect(message.schema).toEqual(payload);
- });
-
- test('it should validate when undefined', () => {
- const payload = undefined;
- const decoded = updateCommentsArrayOrUndefined.decode(payload);
- const message = pipe(decoded, foldLeftRight);
-
- expect(getPaths(left(message.errors))).toEqual([]);
- expect(message.schema).toEqual(payload);
- });
-
- test('it should not validate when array includes non comments types', () => {
- const payload = ([1] as unknown) as UpdateCommentsArrayOrUndefined;
- const decoded = updateCommentsArray.decode(payload);
- const message = pipe(decoded, foldLeftRight);
-
- expect(getPaths(left(message.errors))).toEqual([
- 'Invalid value "1" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- 'Invalid value "1" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- 'Invalid value "1" supplied to "Array<(({| comment: string, created_at: string, created_by: string |} & Partial<{| updated_at: string, updated_by: string |}>) | {| comment: string |})>"',
- ]);
- expect(message.schema).toEqual({});
- });
- });
-});
diff --git a/x-pack/plugins/lists/common/shared_exports.ts b/x-pack/plugins/lists/common/shared_exports.ts
index dc0a9aa5926ef..1f6c65919b063 100644
--- a/x-pack/plugins/lists/common/shared_exports.ts
+++ b/x-pack/plugins/lists/common/shared_exports.ts
@@ -8,8 +8,8 @@ export {
ListSchema,
CommentsArray,
CreateCommentsArray,
- Comments,
- CreateComments,
+ Comment,
+ CreateComment,
ExceptionListSchema,
ExceptionListItemSchema,
CreateExceptionListSchema,
@@ -28,6 +28,7 @@ export {
OperatorType,
OperatorTypeEnum,
ExceptionListTypeEnum,
+ comment,
exceptionListItemSchema,
exceptionListType,
createExceptionListItemSchema,
diff --git a/x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts b/x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts
index 293435b3f6202..f5e0e7ae75700 100644
--- a/x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts
@@ -14,6 +14,7 @@ import {
exceptionListItemSchema,
updateExceptionListItemSchema,
} from '../../common/schemas';
+import { updateExceptionListItemValidate } from '../../common/schemas/request/update_exception_list_item_validation';
import { getExceptionListClient } from '.';
@@ -33,6 +34,11 @@ export const updateExceptionListItemRoute = (router: IRouter): void => {
},
async (context, request, response) => {
const siemResponse = buildSiemResponse(response);
+ const validationErrors = updateExceptionListItemValidate(request.body);
+ if (validationErrors.length) {
+ return siemResponse.error({ body: validationErrors, statusCode: 400 });
+ }
+
try {
const {
description,
diff --git a/x-pack/plugins/lists/server/saved_objects/exception_list.ts b/x-pack/plugins/lists/server/saved_objects/exception_list.ts
index 3bde3545837cf..f9e408833e069 100644
--- a/x-pack/plugins/lists/server/saved_objects/exception_list.ts
+++ b/x-pack/plugins/lists/server/saved_objects/exception_list.ts
@@ -83,6 +83,9 @@ export const exceptionListItemMapping: SavedObjectsType['mappings'] = {
created_by: {
type: 'keyword',
},
+ id: {
+ type: 'keyword',
+ },
updated_at: {
type: 'keyword',
},
diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update_item.json b/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update_item.json
index da345fb930c04..81db909277595 100644
--- a/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update_item.json
+++ b/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update_item.json
@@ -1,17 +1,18 @@
{
- "item_id": "simple_list_item",
- "_tags": ["endpoint", "process", "malware", "os:windows"],
- "tags": ["user added string for a tag", "malware"],
- "type": "simple",
- "description": "This is a sample change here this list",
- "name": "Sample Endpoint Exception List update change",
- "comments": [{ "comment": "this is a newly added comment" }],
+ "_tags": ["detection"],
+ "comments": [],
+ "description": "Test comments - exception list item",
"entries": [
{
- "field": "event.category",
- "operator": "included",
- "type": "match_any",
- "value": ["process", "malware"]
+ "field": "host.name",
+ "type": "match",
+ "value": "rock01",
+ "operator": "included"
}
- ]
+ ],
+ "item_id": "993f43f7-325d-4df3-9338-964e77c37053",
+ "name": "Test comments - exception list item",
+ "namespace_type": "single",
+ "tags": [],
+ "type": "simple"
}
diff --git a/x-pack/plugins/lists/server/services/exception_lists/create_exception_list_item.ts b/x-pack/plugins/lists/server/services/exception_lists/create_exception_list_item.ts
index a90ec61aef4af..47c21735b45f4 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/create_exception_list_item.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/create_exception_list_item.ts
@@ -64,7 +64,10 @@ export const createExceptionListItem = async ({
}: CreateExceptionListItemOptions): Promise => {
const savedObjectType = getSavedObjectType({ namespaceType });
const dateNow = new Date().toISOString();
- const transformedComments = transformCreateCommentsToComments({ comments, user });
+ const transformedComments = transformCreateCommentsToComments({
+ incomingComments: comments,
+ user,
+ });
const savedObject = await savedObjectsClient.create(savedObjectType, {
_tags,
comments: transformedComments,
diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils.test.ts b/x-pack/plugins/lists/server/services/exception_lists/utils.test.ts
index 6f0c5195f2025..e3d96a9c3f6d0 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/utils.test.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/utils.test.ts
@@ -5,15 +5,11 @@
*/
import sinon from 'sinon';
import moment from 'moment';
+import uuid from 'uuid';
-import { USER } from '../../../common/constants.mock';
+import { transformCreateCommentsToComments, transformUpdateCommentsToComments } from './utils';
-import {
- isCommentEqual,
- transformCreateCommentsToComments,
- transformUpdateComments,
- transformUpdateCommentsToComments,
-} from './utils';
+jest.mock('uuid/v4');
describe('utils', () => {
const oldDate = '2020-03-17T20:34:51.337Z';
@@ -22,59 +18,43 @@ describe('utils', () => {
let clock: sinon.SinonFakeTimers;
beforeEach(() => {
+ ((uuid.v4 as unknown) as jest.Mock)
+ .mockImplementationOnce(() => '123')
+ .mockImplementationOnce(() => '456');
+
clock = sinon.useFakeTimers(unix);
});
afterEach(() => {
clock.restore();
+ jest.clearAllMocks();
+ jest.restoreAllMocks();
+ jest.resetAllMocks();
});
describe('#transformUpdateCommentsToComments', () => {
- test('it returns empty array if "comments" is undefined and no comments exist', () => {
+ test('it formats new comments', () => {
const comments = transformUpdateCommentsToComments({
- comments: undefined,
+ comments: [{ comment: 'Im a new comment' }],
existingComments: [],
user: 'lily',
});
- expect(comments).toEqual([]);
- });
-
- test('it formats newly added comments', () => {
- const comments = transformUpdateCommentsToComments({
- comments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'bane' },
- { comment: 'Im a new comment' },
- ],
- existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'bane' },
- ],
- user: 'lily',
- });
-
expect(comments).toEqual([
- {
- comment: 'Im an old comment',
- created_at: oldDate,
- created_by: 'bane',
- },
{
comment: 'Im a new comment',
created_at: dateNow,
created_by: 'lily',
+ id: '123',
},
]);
});
- test('it formats multiple newly added comments', () => {
+ test('it formats new comments and preserves existing comments', () => {
const comments = transformUpdateCommentsToComments({
- comments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- { comment: 'Im a new comment' },
- { comment: 'Im another new comment' },
- ],
+ comments: [{ comment: 'Im an old comment', id: '1' }, { comment: 'Im a new comment' }],
existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
+ { comment: 'Im an old comment', created_at: oldDate, created_by: 'bane', id: '1' },
],
user: 'lily',
});
@@ -83,26 +63,23 @@ describe('utils', () => {
{
comment: 'Im an old comment',
created_at: oldDate,
- created_by: 'lily',
+ created_by: 'bane',
+ id: '1',
},
{
comment: 'Im a new comment',
created_at: dateNow,
created_by: 'lily',
- },
- {
- comment: 'Im another new comment',
- created_at: dateNow,
- created_by: 'lily',
+ id: '123',
},
]);
});
- test('it should not throw if comments match existing comments', () => {
+ test('it returns existing comments if empty array passed for "comments"', () => {
const comments = transformUpdateCommentsToComments({
- comments: [{ comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' }],
+ comments: [],
existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
+ { comment: 'Im an old comment', created_at: oldDate, created_by: 'bane', id: '1' },
],
user: 'lily',
});
@@ -111,170 +88,42 @@ describe('utils', () => {
{
comment: 'Im an old comment',
created_at: oldDate,
- created_by: 'lily',
+ created_by: 'bane',
+ id: '1',
},
]);
});
- test('it does not throw if user tries to update one of their own existing comments', () => {
+ test('it acts as append only, only modifying new comments', () => {
const comments = transformUpdateCommentsToComments({
- comments: [
- {
- comment: 'Im an old comment that is trying to be updated',
- created_at: oldDate,
- created_by: 'lily',
- },
- ],
+ comments: [{ comment: 'Im a new comment' }],
existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
+ { comment: 'Im an old comment', created_at: oldDate, created_by: 'bane', id: '1' },
],
user: 'lily',
});
expect(comments).toEqual([
{
- comment: 'Im an old comment that is trying to be updated',
+ comment: 'Im an old comment',
created_at: oldDate,
+ created_by: 'bane',
+ id: '1',
+ },
+ {
+ comment: 'Im a new comment',
+ created_at: dateNow,
created_by: 'lily',
- updated_at: dateNow,
- updated_by: 'lily',
+ id: '123',
},
]);
});
-
- test('it throws an error if user tries to update their comment, without passing in the "created_at" and "created_by" properties', () => {
- expect(() =>
- transformUpdateCommentsToComments({
- comments: [
- {
- comment: 'Im an old comment that is trying to be updated',
- },
- ],
- existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- ],
- user: 'lily',
- })
- ).toThrowErrorMatchingInlineSnapshot(
- `"When trying to update a comment, \\"created_at\\" and \\"created_by\\" must be present"`
- );
- });
-
- test('it throws an error if user tries to delete comments', () => {
- expect(() =>
- transformUpdateCommentsToComments({
- comments: [],
- existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- ],
- user: 'lily',
- })
- ).toThrowErrorMatchingInlineSnapshot(
- `"Comments cannot be deleted, only new comments may be added"`
- );
- });
-
- test('it throws if user tries to update existing comment timestamp', () => {
- expect(() =>
- transformUpdateCommentsToComments({
- comments: [{ comment: 'Im an old comment', created_at: dateNow, created_by: 'lily' }],
- existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- ],
- user: 'bane',
- })
- ).toThrowErrorMatchingInlineSnapshot(`"Not authorized to edit others comments"`);
- });
-
- test('it throws if user tries to update existing comment author', () => {
- expect(() =>
- transformUpdateCommentsToComments({
- comments: [{ comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' }],
- existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'me!' },
- ],
- user: 'bane',
- })
- ).toThrowErrorMatchingInlineSnapshot(`"Not authorized to edit others comments"`);
- });
-
- test('it throws if user tries to update an existing comment that is not their own', () => {
- expect(() =>
- transformUpdateCommentsToComments({
- comments: [
- {
- comment: 'Im an old comment that is trying to be updated',
- created_at: oldDate,
- created_by: 'lily',
- },
- ],
- existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- ],
- user: 'bane',
- })
- ).toThrowErrorMatchingInlineSnapshot(`"Not authorized to edit others comments"`);
- });
-
- test('it throws if user tries to update order of comments', () => {
- expect(() =>
- transformUpdateCommentsToComments({
- comments: [
- { comment: 'Im a new comment' },
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- ],
- existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- ],
- user: 'lily',
- })
- ).toThrowErrorMatchingInlineSnapshot(
- `"When trying to update a comment, \\"created_at\\" and \\"created_by\\" must be present"`
- );
- });
-
- test('it throws an error if user tries to add comment formatted as existing comment when none yet exist', () => {
- expect(() =>
- transformUpdateCommentsToComments({
- comments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- { comment: 'Im a new comment' },
- ],
- existingComments: [],
- user: 'lily',
- })
- ).toThrowErrorMatchingInlineSnapshot(`"Only new comments may be added"`);
- });
-
- test('it throws if empty comment exists', () => {
- expect(() =>
- transformUpdateCommentsToComments({
- comments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- { comment: ' ' },
- ],
- existingComments: [
- { comment: 'Im an old comment', created_at: oldDate, created_by: 'lily' },
- ],
- user: 'lily',
- })
- ).toThrowErrorMatchingInlineSnapshot(`"Empty comments not allowed"`);
- });
});
describe('#transformCreateCommentsToComments', () => {
- test('it returns "undefined" if "comments" is "undefined"', () => {
- const comments = transformCreateCommentsToComments({
- comments: undefined,
- user: 'lily',
- });
-
- expect(comments).toBeUndefined();
- });
-
test('it formats newly added comments', () => {
const comments = transformCreateCommentsToComments({
- comments: [{ comment: 'Im a new comment' }, { comment: 'Im another new comment' }],
+ incomingComments: [{ comment: 'Im a new comment' }, { comment: 'Im another new comment' }],
user: 'lily',
});
@@ -283,178 +132,15 @@ describe('utils', () => {
comment: 'Im a new comment',
created_at: dateNow,
created_by: 'lily',
+ id: '123',
},
{
comment: 'Im another new comment',
created_at: dateNow,
created_by: 'lily',
+ id: '456',
},
]);
});
-
- test('it throws an error if user tries to add an empty comment', () => {
- expect(() =>
- transformCreateCommentsToComments({
- comments: [{ comment: ' ' }],
- user: 'lily',
- })
- ).toThrowErrorMatchingInlineSnapshot(`"Empty comments not allowed"`);
- });
- });
-
- describe('#transformUpdateComments', () => {
- test('it updates comment and adds "updated_at" and "updated_by" if content differs', () => {
- const comments = transformUpdateComments({
- comment: {
- comment: 'Im an old comment that is trying to be updated',
- created_at: oldDate,
- created_by: 'lily',
- },
- existingComment: {
- comment: 'Im an old comment',
- created_at: oldDate,
- created_by: 'lily',
- },
- user: 'lily',
- });
-
- expect(comments).toEqual({
- comment: 'Im an old comment that is trying to be updated',
- created_at: oldDate,
- created_by: 'lily',
- updated_at: dateNow,
- updated_by: 'lily',
- });
- });
-
- test('it does not update comment and add "updated_at" and "updated_by" if content is the same', () => {
- const comments = transformUpdateComments({
- comment: {
- comment: 'Im an old comment ',
- created_at: oldDate,
- created_by: 'lily',
- },
- existingComment: {
- comment: 'Im an old comment',
- created_at: oldDate,
- created_by: 'lily',
- },
- user: 'lily',
- });
-
- expect(comments).toEqual({
- comment: 'Im an old comment',
- created_at: oldDate,
- created_by: 'lily',
- });
- });
-
- test('it throws if user tries to update an existing comment that is not their own', () => {
- expect(() =>
- transformUpdateComments({
- comment: {
- comment: 'Im an old comment that is trying to be updated',
- created_at: oldDate,
- created_by: 'lily',
- },
- existingComment: {
- comment: 'Im an old comment',
- created_at: oldDate,
- created_by: 'lily',
- },
- user: 'bane',
- })
- ).toThrowErrorMatchingInlineSnapshot(`"Not authorized to edit others comments"`);
- });
-
- test('it throws if user tries to update an existing comments timestamp', () => {
- expect(() =>
- transformUpdateComments({
- comment: {
- comment: 'Im an old comment',
- created_at: dateNow,
- created_by: 'lily',
- },
- existingComment: {
- comment: 'Im an old comment',
- created_at: oldDate,
- created_by: 'lily',
- },
- user: 'lily',
- })
- ).toThrowErrorMatchingInlineSnapshot(`"Unable to update comment"`);
- });
- });
-
- describe('#isCommentEqual', () => {
- test('it returns false if "comment" values differ', () => {
- const result = isCommentEqual(
- {
- comment: 'some old comment',
- created_at: oldDate,
- created_by: USER,
- },
- {
- comment: 'some older comment',
- created_at: oldDate,
- created_by: USER,
- }
- );
-
- expect(result).toBeFalsy();
- });
-
- test('it returns false if "created_at" values differ', () => {
- const result = isCommentEqual(
- {
- comment: 'some old comment',
- created_at: oldDate,
- created_by: USER,
- },
- {
- comment: 'some old comment',
- created_at: dateNow,
- created_by: USER,
- }
- );
-
- expect(result).toBeFalsy();
- });
-
- test('it returns false if "created_by" values differ', () => {
- const result = isCommentEqual(
- {
- comment: 'some old comment',
- created_at: oldDate,
- created_by: USER,
- },
- {
- comment: 'some old comment',
- created_at: oldDate,
- created_by: 'lily',
- }
- );
-
- expect(result).toBeFalsy();
- });
-
- test('it returns true if comment values are equivalent', () => {
- const result = isCommentEqual(
- {
- comment: 'some old comment',
- created_at: oldDate,
- created_by: USER,
- },
- {
- created_at: oldDate,
- created_by: USER,
- // Disabling to assure that order doesn't matter
- // eslint-disable-next-line sort-keys
- comment: 'some old comment',
- }
- );
-
- expect(result).toBeTruthy();
- });
});
});
diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils.ts b/x-pack/plugins/lists/server/services/exception_lists/utils.ts
index b168fae741822..836f642899086 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/utils.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/utils.ts
@@ -3,17 +3,14 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
+import uuid from 'uuid';
import { SavedObject, SavedObjectsFindResponse, SavedObjectsUpdateResponse } from 'kibana/server';
import { NamespaceTypeArray } from '../../../common/schemas/types/default_namespace_array';
-import { ErrorWithStatusCode } from '../../error_with_status_code';
import {
- Comments,
CommentsArray,
- CommentsArrayOrUndefined,
- CreateComments,
- CreateCommentsArrayOrUndefined,
+ CreateComment,
+ CreateCommentsArray,
ExceptionListItemSchema,
ExceptionListSchema,
ExceptionListSoSchema,
@@ -21,7 +18,6 @@ import {
FoundExceptionListSchema,
NamespaceType,
UpdateCommentsArrayOrUndefined,
- comments as commentsSchema,
exceptionListItemType,
exceptionListType,
} from '../../../common/schemas';
@@ -296,17 +292,6 @@ export const transformSavedObjectsToFoundExceptionList = ({
};
};
-/*
- * Determines whether two comments are equal, this is a very
- * naive implementation, not meant to be used for deep equality of complex objects
- */
-export const isCommentEqual = (commentA: Comments, commentB: Comments): boolean => {
- const a = Object.values(commentA).sort().join();
- const b = Object.values(commentB).sort().join();
-
- return a === b;
-};
-
export const transformUpdateCommentsToComments = ({
comments,
existingComments,
@@ -316,90 +301,28 @@ export const transformUpdateCommentsToComments = ({
existingComments: CommentsArray;
user: string;
}): CommentsArray => {
- const newComments = comments ?? [];
+ const incomingComments = comments ?? [];
+ const newComments = incomingComments.filter((comment) => comment.id == null);
+ const newCommentsFormatted = transformCreateCommentsToComments({
+ incomingComments: newComments,
+ user,
+ });
- if (newComments.length < existingComments.length) {
- throw new ErrorWithStatusCode(
- 'Comments cannot be deleted, only new comments may be added',
- 403
- );
- } else {
- return newComments.flatMap((c, index) => {
- const existingComment = existingComments[index];
-
- if (commentsSchema.is(existingComment) && !commentsSchema.is(c)) {
- throw new ErrorWithStatusCode(
- 'When trying to update a comment, "created_at" and "created_by" must be present',
- 403
- );
- } else if (existingComment == null && commentsSchema.is(c)) {
- throw new ErrorWithStatusCode('Only new comments may be added', 403);
- } else if (
- commentsSchema.is(c) &&
- existingComment != null &&
- isCommentEqual(c, existingComment)
- ) {
- return existingComment;
- } else if (commentsSchema.is(c) && existingComment != null) {
- return transformUpdateComments({ comment: c, existingComment, user });
- } else {
- return transformCreateCommentsToComments({ comments: [c], user }) ?? [];
- }
- });
- }
-};
-
-export const transformUpdateComments = ({
- comment,
- existingComment,
- user,
-}: {
- comment: Comments;
- existingComment: Comments;
- user: string;
-}): Comments => {
- if (comment.created_by !== user) {
- // existing comment is being edited, can only be edited by author
- throw new ErrorWithStatusCode('Not authorized to edit others comments', 401);
- } else if (existingComment.created_at !== comment.created_at) {
- throw new ErrorWithStatusCode('Unable to update comment', 403);
- } else if (comment.comment.trim().length === 0) {
- throw new ErrorWithStatusCode('Empty comments not allowed', 403);
- } else if (comment.comment.trim() !== existingComment.comment) {
- const dateNow = new Date().toISOString();
-
- return {
- ...existingComment,
- comment: comment.comment,
- updated_at: dateNow,
- updated_by: user,
- };
- } else {
- return existingComment;
- }
+ return [...existingComments, ...newCommentsFormatted];
};
export const transformCreateCommentsToComments = ({
- comments,
+ incomingComments,
user,
}: {
- comments: CreateCommentsArrayOrUndefined;
+ incomingComments: CreateCommentsArray;
user: string;
-}): CommentsArrayOrUndefined => {
+}): CommentsArray => {
const dateNow = new Date().toISOString();
- if (comments != null) {
- return comments.map((c: CreateComments) => {
- if (c.comment.trim().length === 0) {
- throw new ErrorWithStatusCode('Empty comments not allowed', 403);
- } else {
- return {
- comment: c.comment,
- created_at: dateNow,
- created_by: user,
- };
- }
- });
- } else {
- return comments;
- }
+ return incomingComments.map((comment: CreateComment) => ({
+ comment: comment.comment,
+ created_at: dateNow,
+ created_by: user,
+ id: uuid.v4(),
+ }));
};
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/low_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/low_request_rate_ecs.json
index d6d3879e8300f..5950d088d49e2 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/low_request_rate_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/low_request_rate_ecs.json
@@ -1,7 +1,7 @@
{
"groups": ["apache"],
"description": "HTTP Access Logs: Detect low request rates (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "15m",
"summary_count_field_name": "doc_count",
"detectors": [
@@ -27,7 +27,7 @@
"custom_urls": [
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_request_rate_ecs.json
index 876b89b03952f..f888e4d44c844 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_request_rate_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_request_rate_ecs.json
@@ -1,18 +1,16 @@
{
"groups": ["apache"],
"description": "HTTP Access Logs: Detect unusual source IPs - high request rates (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "1h",
"detectors": [
- {
+ {
"detector_description": "Apache access source IP high count",
"function": "high_count",
"over_field_name": "source.address"
}
],
- "influencers": [
- "source.address"
- ]
+ "influencers": ["source.address"]
},
"data_description": {
"time_field": "@timestamp",
@@ -27,7 +25,7 @@
},
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:source.address,negate:!f,params:(query:\u0027$source.address$\u0027),type:phrase,value:\u0027$source.address$\u0027),query:(match:(source.address:(query:\u0027$source.address$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:source.address,negate:!f,params:(query:\u0027$source.address$\u0027),type:phrase,value:\u0027$source.address$\u0027),query:(match:(source.address:(query:\u0027$source.address$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_url_count_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_url_count_ecs.json
index 810c61073ecc6..e4886b531ba42 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_url_count_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/source_ip_url_count_ecs.json
@@ -1,19 +1,17 @@
{
"groups": ["apache"],
"description": "HTTP Access Logs: Detect unusual source IPs - high distinct count of URLs (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "1h",
"detectors": [
- {
+ {
"detector_description": "Apache access source IP high dc URL",
"function": "high_distinct_count",
"field_name": "url.original",
"over_field_name": "source.address"
}
],
- "influencers": [
- "source.address"
- ]
+ "influencers": ["source.address"]
},
"data_description": {
"time_field": "@timestamp",
@@ -28,7 +26,7 @@
},
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:source.address,negate:!f,params:(query:\u0027$source.address$\u0027),type:phrase,value:\u0027$source.address$\u0027),query:(match:(source.address:(query:\u0027$source.address$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:source.address,negate:!f,params:(query:\u0027$source.address$\u0027),type:phrase,value:\u0027$source.address$\u0027),query:(match:(source.address:(query:\u0027$source.address$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/status_code_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/status_code_rate_ecs.json
index a9341e43723a6..ac5bd5e478c16 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/status_code_rate_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/status_code_rate_ecs.json
@@ -1,19 +1,16 @@
{
"groups": ["apache"],
"description": "HTTP Access Logs: Detect unusual status code rates (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "15m",
"detectors": [
- {
+ {
"detector_description": "Apache access status code rate",
"function": "count",
"partition_field_name": "http.response.status_code"
}
],
- "influencers": [
- "http.response.status_code",
- "source.address"
- ]
+ "influencers": ["http.response.status_code", "source.address"]
},
"analysis_limits": {
"model_memory_limit": "100mb"
@@ -34,7 +31,7 @@
},
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:http.response.status_code,negate:!f,params:(query:\u0027$http.response.status_code$\u0027),type:phrase,value:\u0027$http.response.status_code$\u0027),query:(match:(http.response.status_code:(query:\u0027$http.response.status_code$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:http.response.status_code,negate:!f,params:(query:\u0027$http.response.status_code$\u0027),type:phrase,value:\u0027$http.response.status_code$\u0027),query:(match:(http.response.status_code:(query:\u0027$http.response.status_code$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/visitor_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/visitor_rate_ecs.json
index 5bc641315bc3f..f513e53a964f3 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/visitor_rate_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/ml/visitor_rate_ecs.json
@@ -1,7 +1,7 @@
{
"groups": ["apache"],
"description": "HTTP Access Logs: Detect unusual visitor rates (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "15m",
"summary_count_field_name": "dc_source_address",
"detectors": [
@@ -27,7 +27,7 @@
"custom_urls": [
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json
index 27949c76b3e13..046736b6f5559 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json
@@ -11,10 +11,7 @@
"partition_field_name": "container.name"
}
],
- "influencers": [
- "container.name",
- "process.executable"
- ]
+ "influencers": ["container.name", "process.executable"]
},
"analysis_limits": {
"model_memory_limit": "256mb",
@@ -35,7 +32,7 @@
{
"url_name": "Raw data",
"time_range": "1h",
- "url_value": "discover#/ml_auditbeat_docker_process_events_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(index:\u0027INDEX_PATTERN_ID\u0027,query:(language:kuery,query:\u0027container.name:\u0022$container.name$\u0022\u0027))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(index:\u0027INDEX_PATTERN_ID\u0027,query:(language:kuery,query:\u0027container.name:\u0022$container.name$\u0022\u0027))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json
index 899518f30f7a3..ab405d47484d9 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json
@@ -12,10 +12,7 @@
"partition_field_name": "container.name"
}
],
- "influencers": [
- "container.name",
- "process.executable"
- ]
+ "influencers": ["container.name", "process.executable"]
},
"analysis_limits": {
"model_memory_limit": "256mb"
@@ -35,7 +32,7 @@
{
"url_name": "Raw data",
"time_range": "1h",
- "url_value": "discover#/ml_auditbeat_docker_process_events_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(index:\u0027INDEX_PATTERN_ID\u0027,query:(language:kuery,query:\u0027container.name:\u0022$container.name$\u0022 AND process.executable:\u0022$process.executable$\u0022\u0027))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(index:\u0027INDEX_PATTERN_ID\u0027,query:(language:kuery,query:\u0027container.name:\u0022$container.name$\u0022 AND process.executable:\u0022$process.executable$\u0022\u0027))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json
index 1664e19096ee3..192842309dd92 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json
@@ -11,10 +11,7 @@
"partition_field_name": "host.name"
}
],
- "influencers": [
- "host.name",
- "process.executable"
- ]
+ "influencers": ["host.name", "process.executable"]
},
"analysis_limits": {
"model_memory_limit": "256mb"
@@ -34,7 +31,7 @@
{
"url_name": "Raw data",
"time_range": "1h",
- "url_value": "discover#/ml_auditbeat_hosts_process_events_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(index:\u0027INDEX_PATTERN_ID\u0027,query:(language:kuery,query:\u0027host.name:\u0022$host.name$\u0022\u0027))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(index:\u0027INDEX_PATTERN_ID\u0027,query:(language:kuery,query:\u0027host.name:\u0022$host.name$\u0022\u0027))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json
index d83f36db5a491..9448537b387c2 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json
@@ -12,10 +12,7 @@
"partition_field_name": "host.name"
}
],
- "influencers": [
- "host.name",
- "process.executable"
- ]
+ "influencers": ["host.name", "process.executable"]
},
"analysis_limits": {
"model_memory_limit": "256mb"
@@ -35,7 +32,7 @@
{
"url_name": "Raw data",
"time_range": "1h",
- "url_value": "discover#/ml_auditbeat_hosts_process_events_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(index:\u0027INDEX_PATTERN_ID\u0027,query:(language:kuery,query:\u0027host.name:\u0022$host.name$\u0022 AND process.executable:\u0022$process.executable$\u0022\u0027))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(index:\u0027INDEX_PATTERN_ID\u0027,query:(language:kuery,query:\u0027host.name:\u0022$host.name$\u0022 AND process.executable:\u0022$process.executable$\u0022\u0027))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/low_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/low_request_rate_ecs.json
index 54c2f540e334f..3dfe04766a9e9 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/low_request_rate_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/low_request_rate_ecs.json
@@ -1,7 +1,7 @@
{
"groups": ["nginx"],
"description": "HTTP Access Logs: Detect low request rates (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "15m",
"summary_count_field_name": "doc_count",
"detectors": [
@@ -27,7 +27,7 @@
"custom_urls": [
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_request_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_request_rate_ecs.json
index 6fc7ce7e0699d..209b4e66dbac4 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_request_rate_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_request_rate_ecs.json
@@ -1,18 +1,16 @@
{
"groups": ["nginx"],
"description": "HTTP Access Logs: Detect unusual source IPs - high request rates (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "1h",
"detectors": [
- {
+ {
"detector_description": "Nginx access source IP high count",
"function": "high_count",
"over_field_name": "source.address"
}
],
- "influencers": [
- "source.address"
- ]
+ "influencers": ["source.address"]
},
"data_description": {
"time_field": "@timestamp",
@@ -27,7 +25,7 @@
},
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:source.address,negate:!f,params:(query:\u0027$source.address$\u0027),type:phrase,value:\u0027$source.address$\u0027),query:(match:(source.address:(query:\u0027$source.address$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:source.address,negate:!f,params:(query:\u0027$source.address$\u0027),type:phrase,value:\u0027$source.address$\u0027),query:(match:(source.address:(query:\u0027$source.address$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_url_count_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_url_count_ecs.json
index 1c3f9f96a36b4..dea65ef701cb1 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_url_count_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/source_ip_url_count_ecs.json
@@ -1,19 +1,17 @@
{
"groups": ["nginx"],
"description": "HTTP Access Logs: Detect unusual source IPs - high distinct count of URLs (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "1h",
"detectors": [
- {
+ {
"detector_description": "Nginx access source IP high dc URL",
"function": "high_distinct_count",
"field_name": "url.original",
"over_field_name": "source.address"
}
],
- "influencers": [
- "source.address"
- ]
+ "influencers": ["source.address"]
},
"data_description": {
"time_field": "@timestamp",
@@ -28,7 +26,7 @@
},
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:source.address,negate:!f,params:(query:\u0027$source.address$\u0027),type:phrase,value:\u0027$source.address$\u0027),query:(match:(source.address:(query:\u0027$source.address$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:source.address,negate:!f,params:(query:\u0027$source.address$\u0027),type:phrase,value:\u0027$source.address$\u0027),query:(match:(source.address:(query:\u0027$source.address$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/status_code_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/status_code_rate_ecs.json
index df917ed43c5fa..2475b33aa24f2 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/status_code_rate_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/status_code_rate_ecs.json
@@ -1,19 +1,16 @@
{
"groups": ["nginx"],
"description": "HTTP Access Logs: Detect unusual status code rates (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "15m",
"detectors": [
- {
+ {
"detector_description": "Nginx access status code rate",
"function": "count",
"partition_field_name": "http.response.status_code"
}
],
- "influencers": [
- "http.response.status_code",
- "source.address"
- ]
+ "influencers": ["http.response.status_code", "source.address"]
},
"analysis_limits": {
"model_memory_limit": "100mb"
@@ -34,7 +31,7 @@
},
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:http.response.status_code,negate:!f,params:(query:\u0027$http.response.status_code$\u0027),type:phrase,value:\u0027$http.response.status_code$\u0027),query:(match:(http.response.status_code:(query:\u0027$http.response.status_code$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:http.response.status_code,negate:!f,params:(query:\u0027$http.response.status_code$\u0027),type:phrase,value:\u0027$http.response.status_code$\u0027),query:(match:(http.response.status_code:(query:\u0027$http.response.status_code$\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/visitor_rate_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/visitor_rate_ecs.json
index 5ff35a7e2aed7..3182ac3fd3a79 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/visitor_rate_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/ml/visitor_rate_ecs.json
@@ -1,7 +1,7 @@
{
"groups": ["nginx"],
"description": "HTTP Access Logs: Detect unusual visitor rates (ECS)",
- "analysis_config" : {
+ "analysis_config": {
"bucket_span": "15m",
"summary_count_field_name": "dc_source_address",
"detectors": [
@@ -27,7 +27,7 @@
"custom_urls": [
{
"url_name": "Raw data",
- "url_value": "discover#/ml_http_access_filebeat_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
+ "url_value": "discover#/?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(columns:!(_source),filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027nginx.access\u0027),type:phrase,value:\u0027nginx.access\u0027),query:(match:(event.dataset:(query:\u0027nginx.access\u0027,type:phrase))))),index:\u0027INDEX_PATTERN_ID\u0027,interval:auto,query:(language:kuery,query:\u0027\u0027),sort:!(\u0027@timestamp\u0027,desc))"
}
]
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/logo.json
index 40a5c59677147..dfd22f6b1140b 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/logo.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/logo.json
@@ -1,3 +1,3 @@
{
- "icon": "securityAnalyticsApp"
+ "icon": "logoSecurity"
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/logo.json
index 6b02648ccf287..dfd22f6b1140b 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/logo.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/logo.json
@@ -1,3 +1,3 @@
{
- "icon": "securityAnalyticsApp"
-}
\ No newline at end of file
+ "icon": "logoSecurity"
+}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/logo.json
index 6b02648ccf287..dfd22f6b1140b 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/logo.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/logo.json
@@ -1,3 +1,3 @@
{
- "icon": "securityAnalyticsApp"
-}
\ No newline at end of file
+ "icon": "logoSecurity"
+}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/logo.json
index 40a5c59677147..dfd22f6b1140b 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/logo.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/logo.json
@@ -1,3 +1,3 @@
{
- "icon": "securityAnalyticsApp"
+ "icon": "logoSecurity"
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/logo.json
index 6b02648ccf287..dfd22f6b1140b 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/logo.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/logo.json
@@ -1,3 +1,3 @@
{
- "icon": "securityAnalyticsApp"
-}
\ No newline at end of file
+ "icon": "logoSecurity"
+}
diff --git a/x-pack/plugins/monitoring/public/lib/internal_monitoring_toasts.tsx b/x-pack/plugins/monitoring/public/lib/internal_monitoring_toasts.tsx
new file mode 100644
index 0000000000000..b6ecb631d005a
--- /dev/null
+++ b/x-pack/plugins/monitoring/public/lib/internal_monitoring_toasts.tsx
@@ -0,0 +1,123 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiSpacer, EuiLink } from '@elastic/eui';
+import { Legacy } from '../legacy_shims';
+import { toMountPoint } from '../../../../../src/plugins/kibana_react/public';
+import { isInSetupMode, toggleSetupMode } from './setup_mode';
+
+export interface MonitoringIndicesTypes {
+ legacyIndices: number;
+ metricbeatIndices: number;
+}
+
+const enterSetupModeLabel = () =>
+ i18n.translate('xpack.monitoring.internalMonitoringToast.enterSetupMode', {
+ defaultMessage: 'Enter setup mode',
+ });
+
+const learnMoreLabel = () =>
+ i18n.translate('xpack.monitoring.internalMonitoringToast.learnMoreAction', {
+ defaultMessage: 'Learn more',
+ });
+
+const showIfLegacyOnlyIndices = () => {
+ const { ELASTIC_WEBSITE_URL } = Legacy.shims.docLinks;
+ const toast = Legacy.shims.toastNotifications.addWarning({
+ title: toMountPoint(
+
+ ),
+ text: toMountPoint(
+
+
+ {i18n.translate('xpack.monitoring.internalMonitoringToast.description', {
+ defaultMessage: `It appears you are using "Legacy Collection" for Stack Monitoring.
+ This method of monitoring will no longer be supported in the next major release (8.0.0).
+ Please follow the steps in setup mode to start monitoring with Metricbeat.`,
+ })}
+
+ {i18n.translate('xpack.monitoring.internalAndMetricbeatMonitoringToast.description', {
+ defaultMessage: `It appears you are using both Metricbeat and "Legacy Collection" for Stack Monitoring.
+ In 8.0.0, you must use Metricbeat to collect monitoring data.
+ Please follow the steps in setup mode to migrate the rest of the monitoring to Metricbeat.`,
+ })}
+