From 4d60e8628716004bb3cc1e89afc3d677fce83413 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Fri, 22 Mar 2019 10:22:11 -0500 Subject: [PATCH 01/96] [monitoring] only create license check if separate monitoring cluster (#33590) --- .../es_client/__tests__/instantiate_client.js | 14 +++++++++++- .../server/es_client/instantiate_client.js | 22 +++++++------------ .../server/init_monitoring_xpack_info.js | 6 ++--- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js b/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js index bb11902f1ff6d..6ebd3fb7fd050 100644 --- a/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js +++ b/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js @@ -7,7 +7,7 @@ import expect from 'expect.js'; import sinon from 'sinon'; import { get, noop } from 'lodash'; -import { exposeClient } from '../instantiate_client'; +import { exposeClient, hasMonitoringCluster } from '../instantiate_client'; function getMockServerFromConnectionUrl(monitoringClusterUrl) { const server = { @@ -136,4 +136,16 @@ describe('Instantiate Client', () => { expect(createClientOptions.password).to.eql('monitoring-p@ssw0rd!-internal-test'); }); }); + + describe('hasMonitoringCluster', () => { + it('returns true if monitoring is configured', () => { + const server = getMockServerFromConnectionUrl('http://monitoring-cluster.test:9200'); // pass null for URL to create the client using prod config + expect(hasMonitoringCluster(server)).to.be(true); + }); + + it('returns false if monitoring is not configured', () => { + const server = getMockServerFromConnectionUrl(null); + expect(hasMonitoringCluster(server)).to.be(false); + }); + }); }); diff --git a/x-pack/plugins/monitoring/server/es_client/instantiate_client.js b/x-pack/plugins/monitoring/server/es_client/instantiate_client.js index c52c1b3aa8290..a4930d9d1dc21 100644 --- a/x-pack/plugins/monitoring/server/es_client/instantiate_client.js +++ b/x-pack/plugins/monitoring/server/es_client/instantiate_client.js @@ -15,28 +15,22 @@ import { LOGGING_TAG } from '../../common/constants'; */ export function exposeClient(server) { - const monitoringEsConfig = server.config().get('xpack.monitoring.elasticsearch'); - - let config; - let configSource; - if (!Boolean(monitoringEsConfig.hosts && monitoringEsConfig.hosts.length)) { - config = {}; - configSource = 'production'; - } else { - config = { ...monitoringEsConfig }; - configSource = 'monitoring'; - } - + const config = hasMonitoringCluster(server) ? server.config().get('xpack.monitoring.elasticsearch') : {}; const cluster = server.plugins.elasticsearch.createCluster('monitoring', { ...config, plugins: [monitoringBulk], - logQueries: Boolean(monitoringEsConfig.logQueries), + logQueries: Boolean(config.logQueries), }); server.events.on('stop', bindKey(cluster, 'close')); - + const configSource = hasMonitoringCluster(server) ? 'monitoring' : 'production'; server.log([LOGGING_TAG, 'es-client'], `config sourced from: ${configSource} cluster`); } +export function hasMonitoringCluster(server) { + const hosts = server.config().get('xpack.monitoring.elasticsearch.hosts'); + return Boolean(hosts && hosts.length); +} + export const instantiateClient = once(exposeClient); diff --git a/x-pack/plugins/monitoring/server/init_monitoring_xpack_info.js b/x-pack/plugins/monitoring/server/init_monitoring_xpack_info.js index 152515fa3194d..39d078c800925 100644 --- a/x-pack/plugins/monitoring/server/init_monitoring_xpack_info.js +++ b/x-pack/plugins/monitoring/server/init_monitoring_xpack_info.js @@ -5,6 +5,7 @@ */ import { checkLicenseGenerator } from './cluster_alerts/check_license'; +import { hasMonitoringCluster } from './es_client/instantiate_client'; import { LOGGING_TAG } from '../common/constants'; /* @@ -12,11 +13,10 @@ import { LOGGING_TAG } from '../common/constants'; */ export const initMonitoringXpackInfo = async server => { const config = server.config(); - const xpackInfoOptions = { + const xpackInfo = hasMonitoringCluster(server) ? server.plugins.xpack_main.createXPackInfo({ clusterSource: 'monitoring', pollFrequencyInMillis: config.get('xpack.monitoring.xpack_api_polling_frequency_millis') - }; - const xpackInfo = server.plugins.xpack_main.createXPackInfo(xpackInfoOptions); + }) : server.plugins.xpack_main.info; xpackInfo.feature('monitoring').registerLicenseCheckResultsGenerator(checkLicenseGenerator); server.expose('info', xpackInfo); From 41d4172fe53836d52cf47bdf5636ba35ff2e9638 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Fri, 22 Mar 2019 11:51:31 -0400 Subject: [PATCH 02/96] [Maps] coerce string doc-values to numbers if used in styling (#33657) --- .../plugins/maps/public/shared/layers/styles/vector_style.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/maps/public/shared/layers/styles/vector_style.js b/x-pack/plugins/maps/public/shared/layers/styles/vector_style.js index 92fdfd4ea65d1..d940cc0640f63 100644 --- a/x-pack/plugins/maps/public/shared/layers/styles/vector_style.js +++ b/x-pack/plugins/maps/public/shared/layers/styles/vector_style.js @@ -227,9 +227,9 @@ export class VectorStyle extends AbstractStyle { //scale to [0,1] domain for (let i = 0; i < features.length; i++) { - const unscaledValue = features[i].properties[fieldName]; + const unscaledValue = parseFloat(features[i].properties[fieldName]); let scaledValue; - if (typeof unscaledValue !== 'number' || isNaN(unscaledValue)) {//cannot scale + if (isNaN(unscaledValue)) {//cannot scale scaledValue = -1;//put outside range } else if (diff === 0) {//values are identical scaledValue = 1;//snap to end of color range From 33083c80eb512ee80c5e9040ac666f67fcfcb6c5 Mon Sep 17 00:00:00 2001 From: spalger Date: Fri, 22 Mar 2019 09:25:36 -0700 Subject: [PATCH 03/96] skip flaky test suite (#33504) --- test/functional/apps/dashboard/embeddable_rendering.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/dashboard/embeddable_rendering.js b/test/functional/apps/dashboard/embeddable_rendering.js index 716d169c490b9..97d8e2ec15f66 100644 --- a/test/functional/apps/dashboard/embeddable_rendering.js +++ b/test/functional/apps/dashboard/embeddable_rendering.js @@ -91,7 +91,8 @@ export default function ({ getService, getPageObjects }) { await dashboardExpect.vegaTextsDoNotExist(['5,000']); }; - describe('dashboard embeddable rendering', function describeIndexTests() { + // FLAKY: https://github.com/elastic/kibana/issues/33504 + describe.skip('dashboard embeddable rendering', function describeIndexTests() { before(async () => { await PageObjects.dashboard.clickNewDashboard(); From 5ff422d3530f25de46b7b7827c5abc37b55d7f5b Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Fri, 22 Mar 2019 16:45:01 +0000 Subject: [PATCH 04/96] [ML] Skip invalid modules when data recognizer lists matches (#33703) * [ML] Skip invalid modules when data recognizer lists matches * [ML] Append error to data recognizer module load console logs --- .../create_job/create_job_controller.js | 18 ++++ .../models/data_recognizer/data_recognizer.js | 93 ++++++++++++------- 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js index 9522115367116..6ab0b02c6aced 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js @@ -25,6 +25,7 @@ import { CreateRecognizerJobsServiceProvider } from './create_job_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; import { ml } from 'plugins/ml/services/ml_api_service'; import template from './create_job.html'; +import { toastNotifications } from 'ui/notify'; import { timefilter } from 'ui/timefilter'; uiRoutes @@ -358,6 +359,23 @@ module }); } resolve(); + }) + .catch((err) => { + console.log('Error setting up module', err); + toastNotifications.addWarning({ + title: i18n('xpack.ml.newJob.simple.recognize.moduleSetupFailedWarningTitle', { + defaultMessage: 'Error setting up module {moduleId}', + values: { moduleId } + }), + text: i18n('xpack.ml.newJob.simple.recognize.moduleSetupFailedWarningDescription', { + defaultMessage: 'An error occurred trying to create the {count, plural, one {job} other {jobs}} in the module.', + values: { + count: $scope.formConfig.jobs.length + } + }) + }); + $scope.overallState = SAVE_STATE.FAILED; + $scope.$applyAsync(); }); }); } diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js index 817176cb78795..158bfd4a86943 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js @@ -63,15 +63,24 @@ export class DataRecognizer { const configs = []; const dirs = await this.listDirs(this.modulesDir); await Promise.all(dirs.map(async (dir) => { - const file = await this.readFile(`${this.modulesDir}/${dir}/manifest.json`); + let file; try { - configs.push({ - dirName: dir, - json: JSON.parse(file) - }); + file = await this.readFile(`${this.modulesDir}/${dir}/manifest.json`); } catch (error) { - mlLog('warning', `Error parsing ${dir}/manifest.json`); + mlLog('warning', `Data recognizer skipping folder ${dir} as manifest.json cannot be read`); } + + if (file !== undefined) { + try { + configs.push({ + dirName: dir, + json: JSON.parse(file) + }); + } catch (error) { + mlLog('warning', `Data recognizer error parsing ${dir}/manifest.json. ${error}`); + } + } + })); return configs; @@ -90,8 +99,14 @@ export class DataRecognizer { await Promise.all(manifestFiles.map(async (i) => { const moduleConfig = i.json; - const match = await this.searchForFields(moduleConfig, indexPattern); - if (match) { + let match = false; + try { + match = await this.searchForFields(moduleConfig, indexPattern); + } catch (error) { + mlLog('warning', `Data recognizer error running query defined for module ${moduleConfig.id}. ${error}`); + } + + if (match === true) { let logo = null; if (moduleConfig.logoFile) { try { @@ -131,6 +146,7 @@ export class DataRecognizer { size, body }); + return (resp.hits.total !== 0); } @@ -155,25 +171,33 @@ export class DataRecognizer { const kibana = {}; // load all of the job configs await Promise.all(manifestJSON.jobs.map(async (job) => { - const jobConfig = await this.readFile(`${this.modulesDir}/${dirName}/${ML_DIR}/${job.file}`); - // use the file name for the id - jobs.push({ - id: `${prefix}${job.id}`, - config: JSON.parse(jobConfig) - }); + try { + const jobConfig = await this.readFile(`${this.modulesDir}/${dirName}/${ML_DIR}/${job.file}`); + // use the file name for the id + jobs.push({ + id: `${prefix}${job.id}`, + config: JSON.parse(jobConfig) + }); + } catch (error) { + mlLog('warning', `Data recognizer error loading config for job ${job.id} for module ${id}. ${error}`); + } })); // load all of the datafeed configs await Promise.all(manifestJSON.datafeeds.map(async (datafeed) => { - const datafeedConfig = await this.readFile(`${this.modulesDir}/${dirName}/${ML_DIR}/${datafeed.file}`); - const config = JSON.parse(datafeedConfig); - // use the job id from the manifestFile - config.job_id = `${prefix}${datafeed.job_id}`; - - datafeeds.push({ - id: prefixDatafeedId(datafeed.id, prefix), - config - }); + try { + const datafeedConfig = await this.readFile(`${this.modulesDir}/${dirName}/${ML_DIR}/${datafeed.file}`); + const config = JSON.parse(datafeedConfig); + // use the job id from the manifestFile + config.job_id = `${prefix}${datafeed.job_id}`; + + datafeeds.push({ + id: prefixDatafeedId(datafeed.id, prefix), + config + }); + } catch (error) { + mlLog('warning', `Data recognizer error loading config for datafeed ${datafeed.id} for module ${id}. ${error}`); + } })); // load all of the kibana saved objects @@ -182,15 +206,19 @@ export class DataRecognizer { await Promise.all(kKeys.map(async (key) => { kibana[key] = []; await Promise.all(manifestJSON.kibana[key].map(async (obj) => { - const kConfig = await this.readFile(`${this.modulesDir}/${dirName}/${KIBANA_DIR}/${key}/${obj.file}`); - // use the file name for the id - const kId = obj.file.replace('.json', ''); - const config = JSON.parse(kConfig); - kibana[key].push({ - id: kId, - title: config.title, - config - }); + try { + const kConfig = await this.readFile(`${this.modulesDir}/${dirName}/${KIBANA_DIR}/${key}/${obj.file}`); + // use the file name for the id + const kId = obj.file.replace('.json', ''); + const config = JSON.parse(kConfig); + kibana[key].push({ + id: kId, + title: config.title, + config + }); + } catch (error) { + mlLog('warning', `Data recognizer error loading config for ${key} ${obj.id} for module ${id}. ${error}`); + } })); })); } @@ -218,6 +246,7 @@ export class DataRecognizer { end, request ) { + this.savedObjectsClient = request.getSavedObjectsClient(); this.indexPatterns = await this.loadIndexPatterns(); From 45d2c848263c1ab08e324116407d6c25d52620dc Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 22 Mar 2019 12:59:53 -0400 Subject: [PATCH 05/96] [Uptime] Add first draft of uptime docs (#31814) * Add first draft of uptime docs. * Add first draft of uptime docs. * Implement PR feedback. * Add role info to uptime docs * Impelement some more PR feedback. * Attempt to add more copy focusing on the 'why' of each piece of the docs. * uptime docs: grammar, formatting, order * move location of uptime docs * Implement more PR feedback. * Add screenshots. --- docs/index.asciidoc | 2 + docs/uptime/images/check-history.png | Bin 0 -> 301647 bytes docs/uptime/images/crosshair-example.png | Bin 0 -> 98990 bytes docs/uptime/images/error-list.png | Bin 0 -> 90328 bytes docs/uptime/images/filter-bar.png | Bin 0 -> 27466 bytes docs/uptime/images/monitor-charts.png | Bin 0 -> 120607 bytes docs/uptime/images/monitor-list.png | Bin 0 -> 212495 bytes docs/uptime/images/snapshot-view.png | Bin 0 -> 84144 bytes docs/uptime/images/status-bar.png | Bin 0 -> 34213 bytes docs/uptime/index.asciidoc | 28 +++++++++ docs/uptime/monitor.asciidoc | 54 +++++++++++++++++ docs/uptime/overview.asciidoc | 61 +++++++++++++++++++ docs/uptime/security.asciidoc | 73 +++++++++++++++++++++++ 13 files changed, 218 insertions(+) create mode 100644 docs/uptime/images/check-history.png create mode 100644 docs/uptime/images/crosshair-example.png create mode 100644 docs/uptime/images/error-list.png create mode 100644 docs/uptime/images/filter-bar.png create mode 100644 docs/uptime/images/monitor-charts.png create mode 100644 docs/uptime/images/monitor-list.png create mode 100644 docs/uptime/images/snapshot-view.png create mode 100644 docs/uptime/images/status-bar.png create mode 100644 docs/uptime/index.asciidoc create mode 100644 docs/uptime/monitor.asciidoc create mode 100644 docs/uptime/overview.asciidoc create mode 100644 docs/uptime/security.asciidoc diff --git a/docs/index.asciidoc b/docs/index.asciidoc index 1574644752ad5..dd29e95d794a4 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -50,6 +50,8 @@ include::logs/index.asciidoc[] include::apm/index.asciidoc[] +include::uptime/index.asciidoc[] + include::graph/index.asciidoc[] include::dev-tools.asciidoc[] diff --git a/docs/uptime/images/check-history.png b/docs/uptime/images/check-history.png new file mode 100644 index 0000000000000000000000000000000000000000..de5b8da2e03768fccc3e49905c67d05ea723433c GIT binary patch literal 301647 zcmeFZcT|(vzA&s<5Ev{Vpj4HngpTy8sEAZWLhpoLq=pazA|lcSq)Anz2qE;|1Ox;E zNGDQ4?+|*Z;d_`lbH;n`duL_-dcXCq<61)4+4a}k-ht|>3Y6sZC-540R6ag6~DZPxPg>WcF6H`JXSEv)Szr%pW%jE*IJuCYM%a&Bzv-4Bv0 z@2EVfKR=G8x=)dMgURkS+dFmB3ukEZ!+mu5ruM++$2c#Kg9`QCyF#2$tMb;Jr48Ll&_MSF`W_&ZHY=h{R7P} z2?|en)AaG2@$!u;Z`rSzb&WUDt)IPS1~a)29!R{o`fZ47hR>;oKr8g{dQ^*&#>RKu zH~x$_IwLGLW{*=+rhJsZ8D4h-&Sl(<;ASIdD5!h~zwXlTo?9`VUZBmiKL40Mc=~2R z8oFzOEwu0@-Q|qL1aV=n_Zm(2^dX7*4(QtyE+lCRIwG7;;z63tCgFl=A~9OYS8|Gj zU+Y5-y`Cx`-kuAb$_R5-edIb6cS*rIwl(ejHU)buvu7wwZ&EwoJ1=#CMBuSp94Jw=Six6FLBfbbm3pRdXy^`gVL4Up(b?gCljuv;$F^@gvXgHi zyC8Q?c-bhG;*Bvm*qBsxoZN7n)b}#^mCI)W`6+g9yy8Y~RODZdxqs#TSKXltH2F;K z4TfT;0zO_*{d&Fpl-9V!$eVy4WYTL?`x9q=yLI9I{rL-Lx*vvIcKJr@bbsUu3)^Kf zg-`Duuw7S_XM4-2^OjrT$-8HtNie?8Sp(jgeZM|U)#E#&Q29<~nrGu&)5p8dDTL*C zegtMowmoY6am|(E!yAjVJ*%6Q^gIeVKaQ-)8|rsqZa~dj-JSVQBrQ9&#=mYqQ;Zsud96%TH~%}8lzx&72dSDj@fP6)!ZdN zH1s+{U?gzVQeeZ6Ra2?A$V$(uk;J}}d(4Vvzj~$ZLKWHe>&@50ubCT2Z$*4()1?}H zd-K}^QwgWjPBc!Sg0P|c%QxJqNguOC^0vlIs|4Lxe_ZkTR*yxGcaL=s<+Do*)H?ol z58Q8&Mnrw5+7NWU4rAH7x_7=JR_gK7%s36HJ6EorhR8rDA#~~S&Y?Z>*FW2+^L!cW zyJjQdcBdp!S4mn8@c@ze>67WF$&Z3650TGOpP`)9XFffNZL|Eq(ebAFV@GPMb&fUM zil_LX80so9`f61{?bBS3R&UON<$~IL%Jb{lJK6f0zKc}-Px{aIGi2xW-?o{xu`AKB z*|UMzDD#e(tfz9&5rWQ$gSN!2 zgl5>GWF<~6Zd~A=;76MV1IZ6e!@OOnW>kB!HH$+Xy0)9J{h%mNk$OaaT23wJdR=^IoS?VnQNTxiE<>vDm&xn(j^e)mR$dTwbjH zs6GT$f;p(kXW0 zI%2TFX$MDY$7K9PoGMF+SL)VQR zv$jMPz3ruXNpa!g?Tc2I`hE+cL|*WsGN*b^`<%LuWtpn_MmhWI%T%<5ywkjcFWcw9 zE(h|X_v!qTDboBO257#PrYs|i^%qsUm-$*%M|P(B`R13%FQHd1*N1Aetc&#s3QBJ5 z-kmJ|ZXMm5{80Q6Pl!#h#e=S}F}kCh&9W9M=tk`vZJ3>HqV7mY`C@ta`swxb^&~QC zYFc)E#XhC0oFeQIk&}_`oRrF!5^J42yMBwk{!nNYU7RTHIGe8HStMwgl$a}$AbRjv z@TRy7%xFW)@N8a?=(`3LOk_{j+?wdR5&7X+hO>zKjwWC7Mf)X7?ry_AK!5HR%S7a5 zDQ`VNU(tGt{T%SwQSCVHN<;yte8lw>o!Ez+PdX(yy5E~W?(7gq6mnDz=mYDrt)O?% zV{xN=6j3Xk_na+e@6OnmbaZQ0L?4pEw35{fA!C^pPA=i--Z;*9s9SBvVe}?^({IB^ z=cUnCqaT$&JSKYl4T6V)-MJspW^y|im{xv%p{RE6Mg3TMU;1?=AA{L^q$}oNX1zUu zf|8tqyvpYS;bX?*lE+|IsQ+NlitMD%)#IVs9@xxmG&cBLQ>+r>leQB2> z8QDAFOq7GsRHenR?xb$(Pst^(!4;nV+Z}u>hO!Vu#anPHl;oE18}Q8sjGg%@*VA8xKTHmJoI7!lY{i6_vf9gy>6cEkp0Q?pG~~webTZDitZGA znbMvw7_i8j-JjZN!6)*|JcT_wnEs&Ar{SM@HFHz#Qt@Lw!z4w?-cgCF?Fr25qOwjE z$w6yVhE6p-FZyR}j`Dcx2Fj{RMfF{(23$v{ zJY8C*!!$&_91|<9zu0WxS$rze^O%SD0yJ z!9Mys4~`Z49S7?A-74Lam&xZV_wVj6G&*?W+p#X*$3Hc8LkLLZU{=|FMeimx;vQnq zNZF@*^Vz=hnr1f(y^kHtetUmD#oNblMQt7jV}+-AR4pd0R!QSHYaE&0GJ0&>TxuL| znN+Jx+3|Ki9@$|hDB;FO@;>LyV3BpgK9>#%k0a96AHxL4UVvUUUR6;!=TSxaGWo*S zubvkcw<3}~wcka+zw+1nOh(kgwe?Ti6qsZQPZpnI{MPsBlw8Lp<1C(_^)r1KoiE4l z6Q5gVMrhwfR4$2u;jPSLWT{6DSujBV}IsnaRe&$V5(Rg@*n9PN2c z%pFZ3ydL&1fZnH0NqI;BAMGKoCO16n?HpVrJfv^^-a`WTeA3K!>&EY0Ty3RqX{)H; zkau*3+z{ry%gcXDhWy5j8&b~Z781`MJo?vg;4kT0R<5ouB>4ECP$(}{h}Y5Cl21Tf zT%3aWQkYe&K5E=y2m?UK3MCH&^Lfw@w!N z_rE{(3GuN0Yb6Jle;o@rAm7P1d;+}ueE*&s7%FwrDxq%e0kPA5U~La^Z~@kk5fr&A zBK7-#|MAsdOa3xc=dYmxf_Lx!I`o&X{xwvJ@8k%-9O(~u{oV=yOom*F@87@&zVgO% z0r+6FexUXo_)T(x9N?D&@Z2Hjen_hnU^fKt}?e(Np z$eSe0Y4;(67)Xk@?6RvSR1+%QUwd4QEz7Q-Mqjx|a`wXI8*(pCohIUguhk9h1rV{l zPiA~ib^*LkMf?hFKTt;r)AsTzYDj635bX@%pI*7o_f6zfR z5B|T#9a&d=aXw6R2+|{Zzku-2b!yJR??M)3s&h7dH)3o??}`{^KwPab=I(H5ocx~* z|FSEeKHAm2tpmTjIvE^av8plHY}RHXlBW+!nRo&`Hy-}XUt=Pb##YU-Ss{NjpD zG^SM*oV$!kGb^2sB}&}+N&s?8M}ecwmMTk$Bvbm(&A@Y%9zN(&rc>R#KOjJyloe(L zCJ{n;va9EvI}2*hFv>49Jhn7mBZdaup3CJIhN&hFa_~!1TmZ*(gc;8)A4YqM5~UKF zfc1i_ve@NP$pJkA@pu)jx%>7m``@DTUw~0p0!Eaa#TA^LH3uMBh@n9yM%6i+u@W&j zP6JqXt}i~RX=;BWz{F`Ox2z?YuZB_D)9yNawLq`fs@s&d&cCID_heT>H?_s9yduW@ zh(U?m%sC6ieCLhn)^&?I!uot#c#D=1f=2$07d5LwSjag#eSX^2A2-1UZqY+t!43tJ zz9^@I$ zH95EQ=xvR4lnrso9ImB}lr&zFWK)&i{;XfYn{qYGJ~PSvZM&zDey;rfoUB@)B(9Qk zaISh&B>Y~A>NeWow)3+gk&2nBj}R9LuidxW)-(MZy3svQ!^Z1ZBi}jfnR(tD*}#jZ zl#ui@ArtR9nO1w@)7STpwA5T~Fs#B%ku{Ab5A(tq_aBb94KNFMPUn9b9Q;Xm_xPu% z)sOu7?fBfQ$V46S6{7gKFIg`19Ej86l{%f#h$O0fBRf)IaOstcSvVTp+c_QI||t%~#q4XfT6Axri1D6-A@9NYDBx1nmZG zyK@}EdQtYSmb)PQ!gFZ;M!bx)+1IJE+4FHd(JsmY284|EYY|>IRQ^jj?DIDFsTYEH}J5rP5SmSeusOxo^Srog1L|%M| zAj*J=DpMNf4VfI+Z~mkJ&pN%=zx|s6SSw!;7BOh#!`dme zw0uo$tykMDv|n)ebqaNoB%j8HWM|erlYD1Y^1)84Ww!-SxAP#*kOL6!NQH~UA%{vr zi-RThI+H}Mc5?*Tw)em>ru_KOuh;oN74)r^PC8McA3v};)e(SFTcT~XW2m+58a72$ zBxKAKufRxWR%I7wy#;V2_Rcfe$rr$2O?5a?@~6l!_0g;7)*b8ti#n|<7h{hheB}xV zmG9-MUu|}{HKk^K!%_D%8j4+@v;V0~DNY8awTS_vT8$w)Dv!br#cB2PHA}Tu>Rv_n ztLm~cfi3f$*Iw2-;p*^eSeMbH@Q`h&B&tCY>)xg+;5z=Ym@qVq4b0f&d6#@FK3i7q ziobIct=u6{Rzuw}%U2b%GTkJ}+h#9NJI1Tf;#tKQRr7qtsJ@MhdXX5Od-;`{E^Ehl zChKXM>9+7dAl8R(*j-fe6R&}ULdsHJAbX6qlwR}!lc4$I<;r100rT&DJcy`ZIIhOh zVy3ak1+U4WE$%Q<9%qZH_;kv$KX39bA=X1aM7tuuXF*DyAJHAu9LnDh?bWT97B7G~HY26V6r(uOYaO}|TEdtT zI-RDPLxTpsx0mn0!X9Uy z6#a44bkmca_q5?>HK&(;jKz<_8zSrox<4eqrG-b2|6T_Dy5kirFGWk zVd_u6X#9waBco4)BFsU4obo(a5x4g!-SEHP={9^Q-<8|AglCFNaisXLvDTo-={MC+E zeWkt)pju%=pESFf^5r4Nx}(`4k2K1nCTqgZGE8-=^=y9|i<->(W8^!s9Cko_^OJ!c zio4Gjn9aubN<{vcpcK_-Xg4QuZ3=^q!9;gPabNYtP(#v+qd#qPuWK1%B!8BGnBOtT zcs*eB`0;UlKo2r}MJ*?V%^2FUQubi3vweE>nOLc5eVes?0bxrc{6rTf3>p>OS2+&? zZ4wmaHu4+8+x(4!Ys{XN{kTujT!SBrPADQ}**9W@O&9c5O6L(0Zu+Hpof08)W_Deh z5K4^w90fwnCy}{3024jC%{aW?!bBa#p%ye&1A3#=C7x-S==7+oT86iJ?QjTDX0WkX z=nq0wb9rvJ8O3iUSK;1n59o2im68r~Ta9OMvd7n0>kb6HThHEmi*hv6vxhHU_qDH%eY` zsc(zV=zT{FcI0x&p4;XNlF^}xH*8>jI)L(+tS4RV$VmX-)Tvn;J6P?is%}}WYMKm& zDld_raTu+%|4{Y>V%X^HZ~m~ch55+HVWxdK9k70`!B;CBOT`+oY-@w~JxkO2b9ytQ z2cuAIOU!6lvWZxcSK6>cjerQod`e$)Vu;)?TG7~Lc*VVKG(~z3Ck_2pxdi5Yt(8#U zrsr5Att!2OUbgL86D{yQEC?`*ct{%-PYL!uSotwu&|k{l(XPmubXkE3<}r3a)2UKO zZ&Pr}ej}IjBSuweEpQg~pvk+&GnDtw)_+xtr) zKXhjwO&|w%A`{(-lX+^Xx_;3(NU8hk7$Tv%JJEAdF#^f0!=zwxA=fLVwX}1yL)7SS ztucS2zhYB~ca^4UxzGibXos)qtYmnuEiIrk;T$Rq4kx4L_?DAb3;tMVKGR`-u5&rU zPN=3G1Ynh4p*B)b)Yk>Do}<=;LDWiJ zlzkBh-UrU#z++p!Wg84;tr1!WFiV!Dwk$^nxcJ;5mK@{aWAB4+7|RqI7Q~j5zLz2f zJl-XvM;qB5Ca!b3_|PUvbkqZJ*KUZPLp3oj9w*I(O#V=;^wV{*_<8l=Mh?bd!<&VG zJ?bu5%C4wvsAx5~Ew+GIcv!I6DcM}mk`$-oBqV!7YQ8u8*50Fbme#VLZY3pcT21w& zEY~cPoooQ<#N7v=s*#R4M1ijhDKxSS~#1fw5WAsyNLRv_J7MXZm*q%6(5+zr19+Uz{IWE_95n!y9 zvx^|JrCj)Qe}~;i?XNs!IR>yMNWnrz!UMo_n9Q7LoO(^I8fHGcu%SRDr~K+IhE)eZ z*298Br{;ysW?$0P*x@Ih%R>cD&GE-URXBp<-tgoXPL@z}8uYZsaslV$xcr8em@=5D zdV3(@7THCPmU5@5Npw+X=UG9Vayv$rGx>!+qYFC1y5NN!#&{;*r18`6tTfl_i|}MO z&sl@b+@d4Zr80i)_>ov-t#-WG_*Y+=R}omsBd$SLU0lk@JG-*l{(<4SRTWjw9Vym} zQpR=qqtmTXLfFpJu+13sN()O(N}13AJFWT#6GMe`VKVz~cUxrLgWT)^`vQd27SPWszqtUHkZ#H43e-t(-9f4Ndn+oJ)4y4h_O75p>$4lmP*$Qfl zJ2mV+EH3I!km3$@jk3lvy_qP2LL zEx6ovn@Aj>qcAMb${- zCA|-Khmd;s$KX&jGbxj+T%y~owY5_U;?mm&&8sQiiv`u1SECpd!U@uws8ABbLd* z2)rbJUfxn(okXQ$#X~~_s#`TvomFY}2_oGngDR`xQWbh*mHY27X@J91voj{k_c^{; z4NR{BX5{f<14Zo&*;MVW0lH4h@}~?_Qml?dE+{eKbD>t=rfK*nw8J)vM>&pPAjZI< zsk%ZHtfT@~;qkdzYgVYc2;!R~ebtUNitPmOrBi>Cx(%_`&^XmA+SZV7i}TR7D{l#0 zu+JNDfmJ(qK^FEpGqKl{+(ygqZ+@Q4m?{f0F?x?Ub6gEIzUv^U)_w2<@b|bi(MQBd zQKJ(nDvI^eOZ0Bmfu%hG6O`_U_B&lYKaxTBK$7q}YBCw#2F`Amkz_clT)In8ut=ES zXko~!V+`ggwc5)b*`pL4W3+^T6Vc4APu_>i5?+K{-&EkPK^I~cx61U&R9G=#l|vC{ zf5UoAb&RAp(c!M0nCQB^jC$dK-POhFgUXNIzBug25NqJBSUKv3N_&!gB1fat&NpWy z*vI2zm?U{=TbSUk7E8N4pR9W`V1pT2S;~NN?c?pOuzT2TXVjYzTQ)}j?!0ypo}(@^ zaidFYa!tNByP-m{l*%XPcxfR!c4qj!?D1e7foTw5A)uvMzHdQQyfVV>18Iv=mADxu zA?UN+t552-Y#wtSBqSm)i;#4Xgta`kK8Y6?baGK}*Ws6arUG+RRhI@wR#S&Oa6!J) zvfc;myu-H9Tgm24?bNHCmoOQ078~KlGs+FtkBD({Qfbd+3v27x=`H`E!awhFIi-hH z@sF1_&5lmKVL z{LEx9Uv0>?=n$J$O5#@K_{fl1_~^zWm&R>Iy#kTe(oy^|26QAV-3{2mIi;PpgSBHEy&`%>uWVq?o`k&garKt=E%8Sd)TunWEVT~qEmdX zMgABr28eLWXF9tCf0xa}O#~}uzfw@4kZTSQKg^0ROV$9I-Ut;v(2R?fL7)P8%7&`* ztMn_DY;0%zEk#FNqsnJy8G4q4==D%h&YV#~!y0)-t8W0mSG3~iA0ej_?jP`FC(aWi zJEf|$jSJM07A_SB8r+Ur{0&@tfF50+?$69%O9BtGxr^=nR2Fky^f^P_5*`fi8kMc} z#Px3__j@i=CouE7&5ZnExaBNM8rdGmo2J!dyvg>tF2d#@X&rD)$j1Dq`=6@9{t$>4 zJo>^)T!=#XMBo@9w%w3bV~=2bM&2`Z)f5lO0YCfg(=>0TGHr(+H+oi3QTCq_?pjBV z89e!F?+JvMp2xoij{Qo~%~Buj;%jc!RRcnTCoxzlF}y(6=2*`$=W!_o%Vzu9wY6{d0-oj=o8n;C1^N@q z3uWMz2n2%yKFJVeccFECZ79L2K!{^>qvEg>)B0i`59gsZEN}cx!Tn$b+T5C%m<%0gu zZo7}cTBLXZm#*_o&YM zXoKVp1|EquZ)(GjAwZNrEtWvkNacOL#8{Wkh3f|^RnXFeYAoB2VW)Lfm|H6&hf6%8 zzl#RO7*fE~YUH_IaZP+M-+Z2e% zuQOqpJAwYOIu&crsyF+R*858Kj;qoSRe%sNV^tzd2|b)`zqiPhLIDQHtCJF?CoL*Y zjM%8My7@_^sls*?n&CUDionWSJO8S>vZ3KyAaxpGLf#^4ik6kxUrW+9_C42={fxw+ zmjWz9_!i~#<6c0tk8-v2c&ODN%D`|mgdB*AhOo_R5#q+klN5jO?!`(+_KOwe=+TDp zRB)21U%a;FzE#QZGrYm}V)s7QGEFl_FxJjTXg|r|RrCy22qP#du!pO`H}z{7X%U`z z5=M&D9>ww|xoiWpOq&oZ?T!`p+?L=QRNIR(J^ei`OiD^sV&U~xX+y;qK#f@I5A7g@ z)PkpvB5^|S_gHr+J*`2X97*kXk3*5e1CRC2V6&6RdR}9OL&4Zdh<5%smziPNec9D7 z!jE(-G#0nY)L0u=`NTFVqocQm@gVK zk8+?fl)}{R=gVITdlX8qSswFxNmYD17 z#Fh{go|)|VjM01OW`$+6tYYaQ!E0^&acQQ*V5$9n0wtUS#7g_-9u|>lR1BC7UUUmP zT@3cs)?@Cy33i1}BkoI~3kZL+VW)r^KrFCh{X>K&0f9ea&(XjlXyGj1W z*E2i8$*-_TCV5w}tqXE`9W`aoeJFx$MT7vR^6W-qP%s7!*TD()HzzVnnhgap#`njD$OCmDt^~E_|RQd00k9u$p??H zbcSen&RhzdO9E=hk+(V#z!KVcQI;!jb$=-@Y*kN{(gao0c^>xh+ezq=xfQKvVvPT3 zd+<&CxYOvPV0_tu(7n;-P=>kW^{w8nX72-*_aIKrR@wy?pDpj%+QQ3gTeBQ_CJ_yQ zJ$o$&S!odg(#VlHUY@cVKw|oW#K(~te$j6JKn4kgevc;#u>6`Qv3awWu+WZ5w=TUT zr$yHG&d3#H6i-B^+tuO9iuW&vLtaHIW(ksM(K5qVN)(V4&5PD=G`Rp-srdhtLai4PcF<$jubNWh2=Nc&mYG9gbbR_S4{SSx-^jQoHyap|k>a1f%Cr zgnu4Gm+Y~ttD(gL`F0c62^EjaAGe>i3GaZXhcVFw8xRUK*i2fCypM#(ywZ$DJbHOx zcs75+kzueu-Rip>wfpZBuN59fXmg$(X_9mgF^BX`#|>1oeQaGR9Txd%0ltb@n9-Wd zEj#}n$0aR`8!0ja1QWWy%gVu7RCUT6FTE2+XXI5e-=72>6Ywbi#Y%kSjTPc_^rLX zqOMTDkGnaHNcSGpHY+K|ja6-eAA3zS#hQjo?|gZFu&i>DY-EIvbYmu6wUFpB*FUW$ zo{TyrzR^3$UXu}VmdUV<#bBBffB_EpgR&0z`$HZ^_n~^HpIS;w3Df6KbquX=u{JZdq!d zrTByv014W2pt;w1m}|sn_Qiyg93A!d?lhlpvvBE~$$-86q$+uUWC zo;)goOD>~v?`Z+zflPCWqeWiOhh4TH?f7ctLiQc^VVwTNXmG7nhMKHx4Jz#KB4;jIsfi7 z1%)|Y(AB<2Z1;Yg#1SvwK)oSwlz_sd6zUB(nx7lHj4lcdbbEx5A_TKHb(;UNb z>%EP5X?L;i*nZ92fnx61YlgCoavbW_#d{o$ePJP}C!U zyuDp<1@`_sCutTooOsQNgVP%G(@*B;Hom+Kty1Vb12FB?L47!)`z53>9iN?pqH1A8 zn4d&>2B8zJxVrGb1czF7ROR9a^3F@r9!AJo&%tUAp%1YogStXH7-*g=9N%!mvgawJ zIR^jrmOmihvK#PjKkku!)3HnjPp?)Qv1{vy1iXrNJJu5+AqHOiocv0!qICv<9M(x1 zXYv5&b7FJ{gL7%$irDK~f>-sdDt(*m4n7c=gl5ChRS1^GH%Hf~IaJ?XWcsNPu(M)T zyEhA3=myeWN-evM`6dER4X@)wd%Y(vGJSGe@_({usagX&sTOGGtFuT9Xv#-FiP^OD zisb2-OYtE@21uEH`+iNv%j2%?828UITRI@sA8)}jGY5HQQPM-pqia4}F2B#DTJ%)d z;CAWCA$2^@h?c&|o{eY2a(}2X1mkr9+-ZnSFS|*UF1zllLyttFDJlZKCUWrG^kr!y zLftmNgUdk1$m6IacDDHAY%{C2&ZC>!@ds>)L`b0vm$QU`A__N)>}o3ms*|+vE~v

%(&WK*$=|D;H~{cb(lh3is^X1?Ck50 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 z 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 YMbjl8aX>!%58%%uIn@UR_f4PwKbE-3YybcN literal 0 HcmV?d00001 diff --git a/docs/uptime/images/crosshair-example.png b/docs/uptime/images/crosshair-example.png new file mode 100644 index 0000000000000000000000000000000000000000..a9384419b0cfea0ab4362950d9ab18a7446b0727 GIT binary patch literal 98990 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�ZnlqVZLY1@qxY&1uCJ4)tv4sv%r#tC z)1b&xz3lt)jlcg-xr-u#P1k8H&)h^NWvFPVcetHKnSKuYW>Nop-NXc@v|R`J=|KeI zR`A8{Ry#ScRF!4E%xV$KsOP%~O7{bW)g+w@Ae(5{8AWzrj}koGx=f_fuGp>EeV7k! zo)IVwuZJwzK6&e^hD4lsMDb+8;9jYW=3Kmr4)?$SvWg|a`Vx;|%ZY(Y_tK*EsVd8} zy7%4v8~cyD6V^o<58g0fC(29Q&d+>48%a#z)?U0Pf{Ha3$~}UcNNAPGq{8funF|ee zg)Pg)ZWq>=r`9tiqJ`}~QZCB(=|T$kzU7Y!_LCJ+0vhUiOj8%VZ^+|uL}_F)>A4|2 z7j@5EcPAlb>s?C-%ZFg*4I%A|^@(lg^yj_Mqxi*#GL+3FPsrt-*H<^)WX0Z{g_V~g z9}`%NSsJ~|4!NbGGk!KZr6RAqgx`JO96j0B%~RoZ6ukU-cLg59IeCDW z%$;FE8_d_2OH&_7BRn?_&l;_|ioNSK?h3DtmbNX*=OM-}JxZ{fxP*K``~Ia!0#2rf z&Czm?j0?uLCz>0whRAQ^jR$%(OeHRHv&A#zyL&L}H7vM?o4;IxR(b^6f1%848YB

zR56<d(0mN;Zzq$=D(??bEIP`Xk5q?3hQnR>qCEV0OL-2(|3B4sh6lM0OmUNF_eJY z=rzo}nJT>5!c(iTyA2CU-AEGJ1eqU$z48mhtaPh9HggSukGF$vtP2&67_Nu&ItkUd z;f2Asm*k>@-4Uoe#;w@1>peJ(6Mfc%knH;#j10BLB6(61b#hB=V|ilXK%|%G8%p9l zB3Ud;UW4TGWbCz2K)F>t$qxFCpDC2zm_l+0BL9G`(J3P^c)rj1`%nVa_;_9>Q(uqH zJ|j&#+;)m~RM|o#%=J9@BJp!nCJ%L{tC}CiN%m)n0|`8soqmxU+fiC8K9sNN%lKk& zwJiun`FhN@-Q!KJUWi>Vh3x3W45i!Qcxg_(IIN&NdSdRzY3EoOSHJiCkaU_7A2HV& z*Yz>)Ka-L#g^;hC3)c~4njKBIO4E-15fOs^2Q8=gWUZB2*6oGWTZxvYU}BW?k_K<` z>uGa;-*!iq5rc-weraHrj=Y>$$T_FJnUnTdAkACuBH5`Twd1O^#;?FbjKAvVoLXF| zw-NS!OtYG_+HlHPo3r?{+7{0@Up~J-zW*z>h&74vC49GDD6{xhf2p~3 zUNKWZ%6qEr?K=!c0B_B?ci(lF90uV^m$IjD*5z`QPB2A#ILFGB3bmaDIJe&5`=XnbeOkOIk& z3zKfj?}~(>kTZH8?_;`R-yx$OYUfZrDHZWV2}_dW^cl_n!ho(nUT^ZB(k?gj68{Yc z7P^lK<8Ro{^er#?=f4Trz0A>IZ&dH^j;Cw75K2N69yrfrj`4LM3n&m2UKR(XPEvIK9nr`|uQL zoiCsLFyRj3$C#kc(81my)X_h3-pvwQ6D`a-xXCQ|WGGJ9yf z?itU6q59Ev`%@YE5$0Vt7G0mI_w^c^-6Bssi!DQE>cR0^M=$c@3fk(RzX`bF=MI*%HK84-3t}B|R(x~?*yJD^{G~SV=UXSb7n|e> zVSAB3lLaDVgG5q3r)gVOb`9@*e(N{jLa4|yD$PbRwpYioJdfKzCA zXCp!z{S|Kc=+juBftC7FI&Hgj-X-3@58i08n3QGbSst9Inl_=I9s(H9&F{<=SRpkO zu7|U|X>!=s@@X8Az)*#^56K{7X&M1qGh8DCd!CF>oHLPc8e`&cjx-R3=h4XD4Z8~* zomMW8j*(Ex?XfAe1T~tyh5QgFV|{_HnF9PxDOcD_S0o=Mu{U=g)+9mlKv>w%KJZ$+o+EB3=+yI}VU*|ql|KUi6LCRwlPo*Y(gf%h{dXnl)sg{p*O z)O-j|)ic=ts})g-3vW?A=znR4~ROZa|@*T#3CA@P)WVLxsCS^&trthuKBlC>TImX$Z*4z>zppphUoINa32P-sYx0ZP48(0Db2YS$WXZRN4CqY1lS4xi?p5uH2FyC@c^ISIAUs z6|-38T{3JHB(b?ibFTWbFC9RA$6cUL;_kP5#&beYnb<}An1_nzzLvxW3h%93 zbnQeeIO<|&vgAv8T@Y}_Cby@cp}?_`l!iItg@KLp4T|Tz7$hHWqm70MBOW&ej+1a}}yc_HHjKW`< z#hQwtk5j6uSv8kgb`)v{)vFB?Rvkz;`B|cxsX_r~!XGXM677U@)>`X`Kl9M|7Ui+m zwQA4#>=V`|dHlAlq!3-@FLRW9IbNp!ysvS4F{efiKkIX8#IB!)`JeA5R=@dx@% z4{0(Nb4Eiwp0?He1f$ty?pr!clzX;%>|xkH`NE5b*2n58p?aRb-42aL6zr4LN9%MH zmu&JTti$v~Y;!8H&!-u`V8HW!khgots=qwSWxTSP(Snt+GMYt891OlUF0bLk*MG_Z z#TP4e!6W$1pKXm~tgSAg3JX!WP>2%qSHIew_(NWEEK%^WD{%vqxjv-i{^zIA>7cW@ zDNj1uy)e%2M(49>+a|~LgjdyMA0;_%@|x}UyMSGwJ7w2~7>1QN%gjc(px1$XE5wP_ zLLCZ`H^Zs*_+k|p`9ULY5XHRp5ESU!Aaf;;3DG}$p*U1L9>^-2!?FT8>k&71SYYW< zy73%|lj%w^js%^x+4YyE9xo!8{2aJLraoTX2-dSbF4P~5r8m28I!f}`3zC-b`*tuQ z?+N?es|Ax@g_3>_1_pw$BpM>gt&Y+>i{&qaUmLP~`TeX@%z+2}4OKTcTGC|es?L!C z7P(M1uz@w44SF)|dhbmx5;}Rf+^R?^7W7kzQjE_QER4F`;u?YU@KEm)_SqB4fx$?r z*4=tKUrXYGxU@y5pFcki-8k)e?t;!b(IB-$MP3uv{^c`${MTcGKn2ETuM0jHA*GIC ztCtG^!ku&o&fMnLX%%-aOZnHDBNf+(QE;z@r19xuW?0LLqJHm>r1PK4c|<)TSpD%C z&E)D2uiF1Qr_2-i79J60SW|_z!xkS(hw?|23;bnC<3`sEka0v8_VY+GngdZV_ogFU zZ-s8A`7#Cpf{R&@k+Qo2_6Z>sh1rKS8pNvKMpd3cza&V0apD)fege?57i_zT2HJbt zYuf!u7XaxA$#1-o@dqTDT$@(h$H}^F}4!TiQg{8P6rpary`6i{|5okyXB6AuO?o7>sHR_BM9ga%hU3K~v@jFFRt_5zl zb99oBiigv-gN)f;gD8pIhD5Rg{VsT1A6)AXPZRl3ufR;nxp=!&q-TicvsgYGhEDEFV)*gzbp z{c%+RQ{1r{pML0@;a?bxmF-Qf_!+M#38yi$%U+wt?S6LBBWemlBaFGfySq&o^`?~e zy}mEiBO6NJWv=E46=c&uM9z!d1!+i{0sxdi|K+#w_Rg+sp^Qt@A1ZmImFjGblR+?S zP_T2?nNebRKYj7>ZGlZ5cBdO|pr)w>t!K&DxxNQkkh$s-q5IJ1lN{(+9MjB8CO(ns zdOh~jv8@icM1T7+`W`H~@0;fjnIR33?-iPTu?*>V&+0lUFuFZolm)rIJR)k=mb*PR z>IPS|#{Fi*IfpE_>n(^i2@``q*!y_5rMA}Y?*9Gbv%W{yOy@}+^4N7U!#tstG4NIj zOp`dnD;59qP96mgSP&k7yKD^eq%J9;>u$MPI@T-{pR<@@DiLqT{#<-U==?s1#~vsOrA;|D8hjGe&}R4jk1sH@&R!^KI%s_Ji22Qy2e3odT=2iSELaI<0imdXfETkq$GW z+b4vcgbyQN6{k;*!X88aO}D#-ATgEPL!4F$!T8-+V4<2<8Yk&Zt7d?{cijW3sQByl z$I3v4Xj_09xg=hYtClr&vd-8*$QxAdAK`8gtAqVe zx}UL7P>wE2q4^Ub*>pjDUJVQB^hxI?zS*qmj(@n%L&GIHyp8r6=BG)8CfRNO6fN>> zEO`fYlKBdX4#I%W5@e{rMAFbYa&VJH{#d;BEQP|b^KHqMl+-yB3Yw+A=d@#^7P*y( z*8+nrt=p0C6`)iz@)m~TAcQwn%_-%#QrI;y<@kaeFI};yCRe^Z7e9P&GLpz*_H;sW zq8SAb^a8fqInddOVJZxd{L7CjVigpy5XqqK+>-^N#wD?573rQeyao0wo+mKHNkerq zSA;^8m#t8Y+P^bv;6aO;FpH=KVt-W;-S6CJhRkw1r*cX`ax+R25WrtAFbktMiz>?pg#M*3Bduv0l%a1AuKv=+QF1B`!K0;nOg*OwDMV6 zL555?NL~RR$>EV`9|DdPe=nV#++7VZdxbp1U~CnO82rCK)c)={A>=Vi3U(C+eAOTY z_=0W7wg&JXqX6YJZlE}^xTCZ9A4AZ!OEbM_2GL%fGJ4V~io@utsGDK20a}2r9c7Hl zGTuUhf~dMv?|AA@dJ>kgV*;+{6ynjTL9-urR{Yk=)>+%+#E8_1hLl z^LAF#Kx;mDuq{n;w<{0jpG{jxmlQPS|D^y!vL!P?jOyN+oyFU$)cF=8m*vZ%j%D4E zq`Is$Gv+pzxgDaRg-pTN^u;lYz}3|#10^`3>x}4P55+#kOPvRHi!mVASUn9JDRa_1 z2<%fJuMh+sr$(aPe?}fLIL;kVM-1rMP3H=!m#K~DG#dco29D8jQ^`jg2ZMn$-fv>Q zp^Vm3wp4>1j9aI9&ikUI|HY@WAd)3uMU_uwx_MQb#e?!Sm6lyjZ;IqM&wl*7>)^f+ z*)O*O7rcQ(MY_eXzqe3N^*0D)xjzHw%Svnhdu;FrGbG`_uK?K>y_34&k_p7ol6em` zz^?wMg&|-i4tUG=q=8Cq3Gfx{P9bLgQ3V-dgrhetV%i_AX@PiMjepj;%rfhkJfiC@IwPKB0?ML-qKh|*Ur! z#%!;N6g{ZfCG%@eN`j;iua|zN=O6xQqihO{LF>$ml(PG~)K`vKsUBY;k{gPS0{4BD zaWoX{Xp4PO2X2?pIBJd03eE|}5VaKN*-=S0(u|r|4CY_h=_5tI?;OsrQ3SOeKZPB8 z5y^*!{za=KxYYBsSF=?lr0S6Ee7D^H1ST=er{qvs{)?U$CX%~1g<~1#jKV(=GuXUQgfqxolG6TgC$iPfAtKh(TNW0K99U};OA;;7=OKGLXU&~2K6~TG#7Fy4fPtCwksV9B(}f% z9oU<8QCOiuRBwwDC|X=GzoUtDX4fM|Ue6MhKE+4kieuOd`(mF@+zhtTFMl~2F*iTo z?WRvguG>uUHrTa1EpW}#2UGDiB_nd_2lpP25#%zV^m-?31EJL$yqS~+a0l89_Rxi+ zwXObITVjREMLvdEy5|M7Z(wt+rIV9*ruvoWWNOK{(;QSW2xevv+d9Kee{b0!cS)e{ z;k`r!orSnPJjycAiLX@bf2R6dfEtzkq1fx6+nNZ8-|aB#AF*ypBHl%{_`L+6!Ff;4 z_3i|%Od?w%X+ZU{J+>;B)!!8TRxeXt6%c!06j-Js&=(V7r4@q*oTrL+&#>%sG%`8G zZQYWMUVuT{^@9qIa^OLiawniP%##t_H#a@LN2R3R9}CT{YW2g2o>)9cEDayzU{oIY zW^P|lgB@EKGqE**ojy!RRnpB?(lwnl*gVgL!RVZS{6XAv%L}_ko-mtNFuoeMGkLJc zc9RpR_6zdQBpbHUX^)6Akkp&4lEp(=Xv5id!Q|>0?ujxjP|xG?yH$Q*$o85BU+b=h#b-KJdYBMw;%#3Y)NZe|LhXkqW~QBNGMcT+u;ZJ3Hf4wt;`X z@t&E`eeCIL;M}&@PpNjAU@CFe&@7C2Q;Mv&j04%)t566Q3#J`?SR>k|1vsSfC`SWQk0`I8AIZIso zyVaQ8b&HE~y-9491#qT@NJgvDip7_z>01=-@R3$om5=n)a|F!~RUXE<;0|__(&P~C zbf%*TPejo~4vsvzy}B%VEcz)I>@7LPP`OAc!JAAb(WguE{W)Jv5O5?D3r z-q+gAbzAB!eKZ@VLMf2Vud8Bu^ea{_&eA=aZ6kouJ#xNpnCRvCAF=k~`M2M{h8HZB zyma2jy*|)UX{a##E}#$8&wzg{AXD}WFw5EHWX&I+UEE=BK5uFCAkEwO|Ab-EZ`My= zgJ5kQ*e$pa{dPyy;7Zl(fn#{rxG>sUzY@XSB{_#=28*o~Ab^qITs?96l*INk0zb`z zt=ahW))jYo)#cmvAL&jV>K2VQd@5REWW8eVjjW1}C$8{4QQ;$WMw|qXAnXwV?~CPQ z@t0W6U_+$A%j$>^9bOGap``}_Vh9w#=a|?EWrH@H$jA?YQRt7_3DR<$r?U~ymk1zxMk3YuQcJQsxB55V z&-#c<>as&@QLg|k;m;z_SmkpC$IHX*lrg;vA)g$LbJn>SHB#u; zfjn7oEWAavJb$^{;yN`4K*sD91*%t9GB{Brs9AJn&-Lf7upxn33Y0Vus$1%Gr+H6& zbz=)2Gu8t>Uk$s?7t8|VDW&}lzBPKGV}{tdL<)o8^GI&8Urk4 ze=B6HPdzbfuuRBm*W|F>%DKk>xBA>n^1*92%l zF+~&|&S)=H=7}~$v<2B1eJcE6KASm;9XZ@hQpbGMHxK=!1j*eYpT?gF86VG1eR$dhhx{@F}__old)$` zB!Q(_ovBM{2Z2H4-+4?$!PhMT8pBoTiYbXjI zu4q0M3c>F7N6Vt_%tBD+48z+llvc4d0@6P+PI+VKVT-D3KB|E^3Lx4!1%MnnB;^sH zo`KBfJ`JM$f((C9;sy#T1lH2ekxuJO7IF1J>6$$6TLFP8VwCH_^5vkV+uJVgg5mgY z?4`xn;R!f_%1Me)KsF9RT4Cs9LuBa0mcLr-<$HHkAU{9LpPBcyZtd%V%jur6mR%lC zG|n;@V!7((`Mt8OMb?for6$iMwLSeYgIS)+3RE$-L&2K~p)9jEO91;8TXOuSodK3XW( zSo9x;sqG~t_t%(CNO;#TK);*G1t2VQ&JtcP5UR|uE`3DCnv6-Pf?%-^W=;{t!#{Z5 zu$z()D)OOP1XLAIp@>OL8OHc(Rx&>*QJ%Qvg(&E})Qk`kRg#(E1Y%7wLr{xr9=D+( zR5=L<8Dq7#WD=dV?AD> z=Ajj@DKxbb z-BbbAd3^y#PDm&tZ4|k}$$AfGct@%U07Q4@YZ2_WfEg~H88LI0#Sr=jsTRS(_4ry$ zhre#VMGpb~c(y$#f#9}Lo?=R5PUX%<-;~waa-{m-ZRP*w83kT^J;DLv?x>O$h&#Yq z_}LzI9cwprdV?>}kdw&p$``QNO=i1FH4?#~QiA}4ak~a~oRM3-qBs_TS}Kfp6Si?j zVP`Sp!ChewOopZrVJ}~m8v{DYPn*vrK?Y597|Z>2pd-%#iXv}D0f#1bEXsXV@RJMh zjM7G0Si#txrStFH2F>6H)t-*2n(`NC0PG^3V1dVC1@bW#3tL6QEnOrBOXArTh_zlJ z)i*~Q=%};(#m?ZpCproTNU|)jbM!z9xRc+c|ND5P6NJ&rVmbW$Qj3}COG0fu~ZNWS|rX!I8b-RdJxPL)V!-*^23v-*Bh0{ji(I~xTNyN z7^K)dPVe|#2^qB*n&dNYra1Rnh%a7VhM*@2whR8K7xqov(>+lrxqjsKdc0G{cO*&h zHy=qHP(j^t(pEQszvIoIXk4zOZ*v&+Sk61$*G(8<&n1o$4kpDZU^t=vlLUd0Gns%d zM;g#waDFwz9#3Txgzzq9!}>>77%D_ldkgFe7iT{ zULj((vnmu%Z;ZN54FWm_3Oxre-7-E13Q$cr;kc1bXQ^V%x0p8TYLHJALvmX@y9Y5V zjmIw#+!hN_dcpOw@w>~lF9;ZtGzhk-|KCFR|G?TbG{#I}e-Yj@{MdK0Fm~QZa{i%R zI)fIE&%91V2{(Wfi9laNl81Tl4S+N>@jRHjLo^PB60>U=-3`VFaU|6}1HO~;Rh$zR zT0Jru=ApAj`e8-VS#8fLMoKVWRC!r!Ob$cdES7TtP)!L28td@V!6Jm{sPfUO($J1X`|)qQqqij!6Nz>g*`=yPM4Qgsrjr@9rh z;FfH_HMAZQ($hUI_IJf7Olg%NmnU3@&Fg0C+j&u;w*pj})eQR6DWe#B4|{9b`&RN2 zJ?o1%Wt%F1ukj?RuQbCP_7kCFvbEp%K=SRmsw^)@LxB7UzHotvu793^y7wiD$`z!t z{E%o$Ia>Yd+yzU=^cMd|Tn50FF)=|j#&4SZ^kIqd3f+1oRvKzAhcQx;< zKf;}zqh;Wkwd?ouGu6%FhmJaRO-H>3{;bb5{G-VQs@XGyO&$w`on#9TBlBFvg$?>H zabvQ(W+`Z?29>Fv4~7V5@4o680Ai<~q6s13mgBEhuUDv>S!qRW+zBZ+TG;`T4UqW% z3b?azrO7G>nGZ~8WX=u?F1AD51`kdj;ZtpnLU`9?Xf2*+2`OCmvOo(;OtXe^OWJhj zxzju_gVJKF}xWOD>|R|VIXCJ_}l%dVvXDJ+zVoj<`}^u2?*D3*|3cIAV$T&Pu&jtw z>!ymjP<@bwMM?{B7vH?dJf!b2MHw+clKX^Sj6LF&dVGBWIG6IpeSnr&@z_I;&55pS zyB%0GRY>K-Sa}3I?O=6`&oVDjYy;6bz!XL`HY+);KXC{;iuU9yO_YC>Gc^4ch*n?- z_fI=OKj3psd>ggIcy>`S`VpGn)*-9NTN?7}frq^PK9m7#nR0LjA3mkyfurB*P%rOt z@rXgM??iLn?16X#+p#4>cafe%&&L+>G-&PJ}o&QyP~n_2)fT5v^WB1q3b z7g{lc+1XY_#Z(Kf(ixS~JPhERP}*(NF|C>t%Sn;Nma_vShjNA);jpnna|!9&Exgyn zoh;6p*7$&&1)&m+4=^7Mh)^7Jt2Fo!`owiUB8AiDfnQ1$HO%Jt{foY*#-iIA7bjV} zL4vI+1Dg7}>*oyNQ9@G0E7 zDr>uN`mJw@``*Jk#ccN$hIxmARhHvWHClh4V#C?I8*$CXFWaVjf=>-Lqf@R#C=TFl zL`w(u-j?*+Fw_|ZYY#HXWb3v2LWYspkkJ*RIP~0b(HGWvv55N)z-Xj_gasDJMGCTo z*NcUqe#>Vy8sTk+*hpRNZ)CTaa_hIHw+cy8HfTNslXJst$59|Yk)&g zM+6`l?W>=GUMraC-b|@Tt<}7E!bq?-U;^iJUydvB!*_v%OeFu#l>3C$YQ6Q$QPn4U zHCXBMl}Tuo@St%X?%t>4I#E!%u2%h=6bOlRR)w-C{Eph?bpG4S?(m&rS&__~#IYEjxk@=n}B_C8nbwjZ9ZwPYl!_H zdFN|0b=1L}PGd85I4_tZ!#)m3r|(AKTLXKJ9viFZ~46+!p>3AL|D3Q8vH0)yjePc zS-f8gp+9kgKDel^+*kQu1jL+SpEg=!n;(*BceAuqAC6aL@Cd(+IO|TvBtSAIz-`F~ zIUB6WCf$t}kBmWGw@o=cwwYk`!PPX2GBeS!irb})T|oUqTCsyXyzKVb4a3kz8Ao)P zQFR8P=GZxQo}ksrV7K9aeH~U+r)LeKP7Fi1r?Jl1=fu=i`K+k#u@7#cuV=;oN#-8?5OdbgO0|u>pQB`a zfa6Rg%V+Y=fY6rP?cE1p6Z1L^)wgLQ|Bv<3I*?aS`zkN0OwBt7ysr-NT9i6Z0U!)m zINat5p-Q{#Tk$uJ>)pQ^t7-ZF^UB9Q;B`*ii>~wJM2^m76IITtQKr`#8p9V9{eXU3 z&-~tDn#($ucF>*x!oWsw`yu31$mb*gJ84dIn2R+b)M_&##K`Sew--eJa34K9GWeLCOh&q|6g6;lxKWb%HJ!Q$4qEgm1nDes z7P!6ZdZu*}F;8lI_kzX;psblh6cb-Cy2mH;pF@UXR}=6GzbtR%0^s}(8SMEUzYj&LOrN1w=S*Vjlmok)!FOw*f53}{0_LU5_4u*F_1y3oju+rWtbLsU^H-npd_le!lb34dk&o1PJG_S zUy{^(y`u4Phz~2YGwV^zXD~5w2LL;4Cb@MpDTcv4KYfAD4G8N@%)HA&`l9@nw(n&1x z1?WU$@g)Y`OJ(Esn;f#EJMIP^qdn$1;`6s(cLM(Gj}ZGWs_*ZAeC;Lw3hhYloGjn~ z_7iMZ;7u!?v;O!Wm1-d!x)0sdiZO5}qV?W~EF(9h9di??>IwI~3P`03w@u=^! z6r`2g`#KDDmK$()oQkKibt~g75R|re6Y7xj5@oAO7Rw3{(XWl*APqTqkUJm<2zDo5=tp->r)6|-8N3@Z;p2onHgsP_1L$$tb zbk;7V0(=v7_UE!rXZYk0cw_DdronuXD$sPFXk!6>Fw=C+W0R)&_#u~$2GRXxO`AZE zEg>e_Mx48`7)muIHDs{9dRv%2=JMIjrx+pikm)E8wGRg$_W5`&VR`SGDeSZ0lCqPS z!V00zGD$C@f?kX?XHd~Hl6FBC4^$#S>=izJxZ*L!Xne>_dK5ICoUU~50T)1-tG2ju zVuZY3;B7v8;FTpto^X;=^l&~tx!#TO$xAGhTV;{vyf)!#(iOqw;TQQX>(eynC z!DU2i3B?^(lA+8CyhO}kgVTr=GE?qw5b{}VQg>C)b<2oiU-FSX#s* zIg}e~jnbzW-QykEZaH4_XnVr^Fn4uBtb#;HtpCzS(jXi-9X55LMFYiBVHTo)8%%Rc zbF5s_zYSp8&%G1G<&WdT5u`%Ah4)~FVYRHAVe~juUYSV#hOzMsi2u2vUv%Z?HT%t6 zjJ1??slDxY*ba;GlK4G1narr3a5q84gzQ7**Pks6yrfpan?%ukzDJF9r**WxQjGPYcM(_ z?y9K!+o2;BGdx&mY)P~kzpod$s<2dhkc7DZly{ptY{Y|v^Z_ZPP*6ox!{1Klr7+c; zIjNn)=ijcDDz1vPkytj7bSNI^>iLJ*ABGe?gt8$Gy)_K|1RP}+`Bp_B^hocstEVt= z&qRN3Fpxj)`x*y&qY(!L!l>S(lhe=(`Ugp(Bn51M`(SWko?%PcT%(9&S%<2*WNd*r zX*jP$lFj;~7r-LU{4pB@i5^X8%*cthg#d}Xz{u2R?)80f15ZX`s%UME+6bgcx~{=O zu6dzLX-N^44Gf%7vEdakX_lwZn1JAkb9o5B4HRFVSc z9kpPQ4EMkyn-C<98EtPuziQ;o{PVAJ=*1ytLC)JKBXRppAb&}k&pUo`PdJoI+ykEtdLcIW_0Gth zT}?hHPEb`jdqtJ->3NCI2T`(>zS^Y9B-zN9JP-CCcEtEZM*BR?8N+?~i51<5gSbBR zQq%1A>oVp7S<#LJs@qDawd5UGTZY@H{ZvcAk-Ox1Lrs(H^l=|I-0q{B5e4upcR@SA zslMp|5%0}gl7~b2nR_3d-Z)8k$MT)8FHdQTiO)TtSAIfD>vYTetKyTDmy5+0#-pJ4 zsve1<8na!+jdOA-7H^;t)l!y~U{U5IP(rh8t)zv`6D=dUT;g$TlI?oe8?g>VU&@U{ zW<6EY#VtsSt`RORhK?Hn^wQL`OY=i2B;ggW7~&OA?E?ySvM2fyTkF+6$N@>E9ZqLI zywFLbqdFri9b}?0;B=aTqJvL+eJYMi7B#S=;5<_t-(XeusMbP0%0sIVhMkD;IgtGL zhif9)VG?Z^NVY8@0zgkAw-?{ceYv|C!fN*3kYLgrj`Ak^^R3_$YpJ;$o5Nyt7HM2x z()sZ(umPcGBeK_Xd#Ov;j16OUCN-7Qts++`E(rB5lfx~(7;Df{(-+s;2xW!dVv{BA zmHopPjQST!GmpCk=b0LB51dlOZdK(p($6|Z*7S0jbj3=H>&ah~yi#O$4|O(WGgRw` z*(YICP~zNnG+OC#yMymktGJ3j(UHhof zP1&K_e7#(b(U08$6^jw`uD#obuT%V%te&$zzg_u4XXT14G$&*MxN6%0mFU`Z$i za{fz}5yGgE}l<$k-?-jxU3vMP`%x5q*RT{xG#%lAS-dLWtj8vqk&949W3xiNvS^Q z5~I5f5h*bwpS)BgJ^*`LVyJU$!*pz#;1!u{o_`~i$QDxs{VU;Nx^`$~-8Uj~7ZHg+QW0Z5be_D}_3!8K&n&y5JZQ!7RFvo1z_|6933XXaxzQ9FL?*2I)o?U zT`3SK&)g)8c-aAwg!>CsvyoD!-&TwD%s}ODKKCsit$WITm{AXMU@`*0QgYZXBiLg- zcg(U&mHdV9#Ut;>3~4dp9bF`C%-V-2GLD6_9_eY(L>+y7CIur{Nx14r=s||^P>G;I z8?+1f>E1r;v@>uR{j8hlO)?=@?Sr&^iaLN7Z#REL8gsw?hF?R`49;q~RJzyrOgLxn zYfe`eF6md&_0(^NNGa{31Q3e^FlfOyBS%m;KOQJB5`3&I=X6_9P=p|w`)u)B_1Ww+ zZrLmE-;`}1CJ9D=usW#Wke?>Y9golCf9+0~y8TI);VUV!Wn{efsDwd`5!XZ^D{mCk z)?f!Kj2hI{XSX##<{T8sAs>V|LzNE|Z>lvkAb9{Z)YulvPEc}c@_}_6l3rI~xISXaaF@ap$JD(`)8*qqUYzo6K!UpHaY22b z!b`XdXw&fY-$++$Ea0Ka*2k$+Y0$Z|Nl@<)rZjW?Rt#5ThRGlme(Tu4_Lm6`e5Me8 z<2~HH1xI+kWz|EVO6^#%#WDl~I+%hESIm90S^SWWr?Zrmfdbu4zLh^J*VnBd9)~}B zEp8xzoAvJ2ork=d1(QXw7Bgk{S4sQ{Sh5Qf_a55M)PZFTI+Zy(8f^^<5>%;QUOL&G zY&lPq8Pta1^1E@y@f*;&e!0u}x5DHfmgR4N#--qQnL=y=%#6`IX1-D3tumKwO+}5khW5^pCOw4b( zAcao);iNK`zJ&Ol9jbU&IT&Ju36>e2+*=3IROeom{R@Iina$lwdSA=+J^Tpdta4VP zF;b=c&)>>7U%jka3t4`o`#t7JJ@irT5EeYjen2`dsyjn{D??&5I)*H;*-00fq>{Ck zqDqMn()7~GSdnN|AJ@9)<&tT|F0*B~xvqMHgG-xUhNAjPS#I^h8`}B);lk4JVU79D z3Lu$`k#A^PI}*b|>pl7kX>+=q0~&A9`3g~Erb$7au#+MUSZxNh zRaV&s{^@Pu$XsYjlUUBnv?!B7oBPFvy*r6?n`zMM!=#~lJx8GzpkXA^hf;~WQM|mQ zss=!=?Uy3KcZ`7ZlEDatNvM2CsRLho0yT7EtVZ1&kj!k7w%|wc8$$)6du33-Ykzlf z*E=NG_ru3I)=DiqjCBKXjHGh~NfCo{i%2Lbtq!?M4Wl5IV}ghONpgebs5KYKhLHGF zRQQ!Wb)Ikr0uN)Lbprccc8qmGe9fr>J~O(BV`7q{;_*^EVL5Cc<4o0JVYJ)qexg(2 zr%6zNF1qu4HzpBdpu;OgdD%|K;DY59wflRkA*(KaA&pE2THn3L6Db-jJTk#Fy;+?; z@2~0RbzZ|B`sqaqdp~WBv9rcM=XTq_1=Le@t~pfiDLq#Ar`3GIi=f*>9S^Yi$V0K! z%pXFrg$SHqbaA*7Q2n;+^G(kW=Y7#LEM|qLX(7%A*VV2=<|nd<4oG3Bg{kDMElkSH z6?G4l-iukytFlz@B`6E}Z_oJ*cT8a_L4^#q#2b;42dCQf z8&rJP4j$*6r%5R|h@8=#y|l1ZKT;xt1KY@&JeV>h25V-bgah;IwXNZMwz%M-)%}S-t>> z*wy9PU@5@}=7H;_H+7j=3tlbr=eIW%nHGt7SkD9eg!o?n(uM^%hwe87L%81D2-4Fc zi0vvGpX=3oeveCWOyTw_B+PnWpg)MM1hFRy=BtAx5-l4u!EdXo3 z6C3lKwbzzhV zCag$jIq+}KWQTICIuBB029URUGHuQ<`%h!sd$Jh1in$P-EVQ$O&&xG~eMlOzXS2S= zYg0+T8`X5F2zT{HmBREc8mvSmA|rvK60-d!f;o!3>s>L@hPJNKR}5@Jb=6UOnR-p{|i;AUU2R_ zINt7P?S9Riv+M~mt>FV24bFy6TyHmn&r{StQ#+os5dc#fJb0(Gw&lisJS9Zpe57=R zcF}tAFQ)E$f+-IvPrczojl-^Kv`@4fyQRv@EBLiR^i{0|&@C+KWQ*^qW1;D)0~S@^ zY{O>3fya+_AAj0MUl}C;5@5rc=e*7z-(sTBI^+CX{t9SP1kleDVd*r(8{Atq#ikX#RB1}Ed4n)KTR$-?0s?iJKLenu47Wh|o?DyMx$ljF3h@d|}|KnQ~m2b9x zv*dqz{#-99llzJW9;?HrsdXCzNx5!3MJj!NjH8`t;Ao%Sci;yPfXW4Czc|N;e>`lj z^Ct3SbTxK*`^ORy(K@63>E?fXEbww_mD^GPS2(N|Vl&PgfJMEKTz1h~Us5#iqVb0O z`1fn)ByU^}$+>Fv-(%msxUcJ9LUVdA7faqI-rlDc8xYr0UU>MED}OBP+;zl@KqW$B zSP~qI)9UR+v3>XTy4I=N7$C!3LKdF?c;wf+Zlb`N@h`TO{}0vvZ(O3iwnt9K=g;%C z8)A7GwNm3bEc*cp9JO0jQ3Q#QTE{1@wCEH`S@3j?wB7lUYK{E`8UpeWM}~M((81ET zmtmx$pMgGY0|>o=SnN{9xpLJIa?7&f8@|2|yTx=0;LUyX6VvaAU?$9vjQ71fKh{$X zy`d?8-&a+nduNA6ahxFTdH!%xXE|%_&KG{61ZnOUR~ck&uiwP{C87kO1TxB%w7>YeoO}CgSN!*#PWjv%+ zqSA|?Re6dI;Bd+oUoLb%KK0D8*xnF*;=T-EaBS8GcIT)2X;tW%sQ?y0Q3a9Cf`krWi|L{e|c){v3q&6{%Cu=Hu;2@Q<%eI>eF^h2x0iuD~wQ^ zm39e0E8DKg$h>ez5^vlG#QJEy2~pw`C&_YqlFvg5sTXv4L!f=`pUCv-y&K~9J^P*T zpDf__2(jV5XN#nAAJBzy9Y{AvxnglEh{y3-V~GUgwXj?tEYm8aIgoXp?~OcnGZu(r zbN0pZc;-(WZP*>N)`!*{5gb=mVRpwy)^ckt1x*mg&zJMZR(bc~x4Z9vgvX~G#V-+A zj+V1GVBoeyx$(%y2&9LMxJPTlKs&HWV`WkEx%#mZ5xtJ+(GiLPMy(ntY?@&?5jxL#Z*S8P8Zk?;r1l>O@(Ku9Y}t#hyRc>t>`M5 zGM~?P2D$^>3umbmMuxqc?0ej?|v(D zZ?j0db})~ZU;osiz+Bx7F9&kHt?qaqsvP~$2m|^Gu2NfamrA%->BWdOJSSXVfP%F!}+n%sjjrNIjKyv;Wdgt-*rZntX-xTUkR^Yqt0}3C3bjas{ z<=iK?{ed1n68j?l7>&yof=>NevlvZ!%78CU1;mHt`uouvJE9MZTc12(veb@Kh8qZ*0)=V=JK%aR=bI?bnQ#x{7tg zQ)Xe-;OlhGzf${vM}il;fT`*bTC_Ip>T%qv3Utde8A-3lQcV4AXIrmTnw?jg^zszI zT8~rY3;FMWfL5$5sIcRn#0eyztG=_P=tZd^<7Zhtim_oGoeV;>nSX9+fTS-BXmWx3 zY>rL;f*N_we)!Ehbh2VM{U({UrNW$}I(QGQ7EwoU$BkV^87X-pU6wDcD=MES+r4ea z1|J$g9p3ilx9h85x4fqbCUD?1?Bx}(D)!CwggQ$9>X#Y^>!H0qYW>qI8zEw z`c?Qd7TiViA5s-{7eGF97CaDky9~XuTFtmnzUiZr2q*CBJo5n>Bx(fV{81ybUd6a@ zl|9*up#-Et1ZQyPv28wJIL2*v#oCs=2x0|VX+=Djq(FZ7tcdQWN0dolc7}!@hqO1c zG9&Anc^URhUgiD55vD|3Ud2^fl>w@n-#Ot;V@kAoZ8Djl!PRVOU7ZZi_x~eoe=@#v zl;1IB?{3YXI5poj#+(f4-u|K((66m>YMCuZeqgL$C}?_jAfF?Dwn)UHH;F53p)JsK zX`R*;M)=u~exmbPX;Fz&j>G^^(BP7<#-IEi5j|7+`H180j2OL|W5i@6O+*U7dBk)6 zpQ7Qf*taxQK=tVB$8$Q>LRmyCIr42I3Xp7R{ha8=b3b%qD&-m7fkjqc{u7KDM*E8= zPzn2M;Rcjd>8u#$v`rza8nl;G-YG>QD28Lsi$k=De~>O-0cW>m08G1f`)NJOot7#} z^>LtKFcmmOP80`)78UD%2JmNxL?G+I*M$e~3atOG)5zLZAs;_a&c)?fiZC0pB2jw%Q zUN5$xg>NbmGipK7fzs8^Jgjfw1I_znc>&h{6ILSvvN|AvltU9l#2RMU6-UY8hq@yf zMk=PDiq@%Q&fST7=jbAi=7<%5RbD)VN71N80PWetuAljff#Ju|cmYi%66G~^JCH1? zWDcW%2eaF6#GgT2FG6xhvKdS5LWjvjL(;}=aXah^dBsQbXS?=P0N|6hjGui5E^I%aZlJxaG9X_&?N@)LkGf4--7gF^zV}d|1(K!FS$2 zVUJILs6kFNRvUTaIANVVfp$>JB*`7Cp=MMKuAO$?bi1Th?lFsC6$1ik<7ovXYrgI; z_GKJq;sUBtFr_-@CS+tx(yGA?K3CMwil!r-Za7NZEzLJ9#y<(j_doXT0M!u(h|uNC zAKuwNe!=rdrOb&7mB4Hp&I~k)jd=EobfVZcRQTgFYr!~f=O9lq>2m^`X;1zcZa1#M7z&>e1lR zhcx~EitX9~;NQ}Dk|sX&JMi`E__b+AjC_@9rIpg60cwh#pJ`QM@f)p*!NBovY{(8?!Z%8eCs&PJ%G<-l`*fPTmdb(^ANo|kI z)35=f4*GC_uFR_fMIomH*J})Y5i_c`INo0$Gy-b*vbqBBDcQRd`Nne}XZ=u2R!`>& zib}4(>XZRJn^nOpW&2ocDsO-z^&X}o$#i&Jx`9I@laivdbt5NAI$i8d-fXLlFg~5* zN7)^`fe`?~?_Z&x-1e>3*_J~lMC}0ix3#MHS09}!f^uH4ML&F0b< z$7)(jJ^+e&5a>3lKLeo>uxB51?=_v6{LX4#XW#7P#jH_U~&Y!OxFPm3sg(#vkl~l9{d8N7NpWDhKno zX+WRGGW*Hbu>e(lf527XYHUZfOolVVWkY=; z?;-zDZupk~)HC_J0AjK`en&HYCZe-GUxQQ+jgMkJ*f?gQH0qO*Bn)i>LNs)fQFEM; zr-=87>`fBL${pSu1cEw!kDN~;IR=5PSYI2!)$o;Wb-bt0+ybrIM&l8>ys2Va^l}SR zlv_kMArvJvKsN`U*9GWv;RP#PmRx<4{qe-$=m7GAOZI{i5XghUtX_o_Iq90qS!~rh z?PQAx9^iCT>S}(VZ+#pGxL8AszhiwRq{yZRBEklgys4tzZkca7m!Es#xpcDHn+$rt zM}>+W*I}o#4Ctq9^NRu&6lhygb!L_IJjQ7Nk}FARgJkPZDbt6r4VJ&nI!~ zO>iQH4qDFEX8=85A88f5yXli`73$|{;3=4~*1t$;Q!CrVtx%WSomM7=K@212jY#b= z9WD6s>_i3haSr?M`|$=ZiUm-JGggqT_K!{aBR=^d)2Gr%34E?eH?|XYPq(!Mz)^sf zDBpk%@!k+}Nq~s-5Q_zcHq1fDpT>09LLZ6l#1tMX*8wu^9d$pQzgs@G_a-Bh?)d4LEa7UZ04c;xF0Co8i7wzB`4jl$r?i ze|lp-pQCyo5e27R(%EM9GZH3ruq80sc=pPx%mPl4*7@p@sN8}6t042dDzZFb0TD?B zrj7Y4W$~lqg=I-@;Ftl3-@?@gS4t^drFvIb$iWh$&eF@NSTa|f074!LXBVwhpgwE7 zZm8%FZP`D%!*{X#SW$3#VwhSaARX(OI0m=<#sl*SNN@-d4@oJr?=UUSm~;6|y&gw7 zXjDWo3&<#Z`#8s(Dwc-wzCZmNYY@gfy8@s8$&;ch)ewB z4mvzY*eXAnFl{h(y1F(>nuU+7cTe^24Yc4U#QQPe zYXw*BrFP;g44F+OU0tJpDLfApA1)pwQ5jchcf5TU3F9dc>fXBf&l=jT#*UpgClCJe zDe(1Ip!1esF!hmDOXMi~ebItR@HXe#*E+r4Iz zd1LeUk!)icTNbedC(>|e+l&wIkBSjn9%L&_J7*DA1_Q_2R=iTLv1*oWYij~uHSiLg zMf>f7DrDvtywLd`8X2j-2k$jzLo-xNz9ly|BJMn5HBzKNnRMVlQ_Ae=ZP?qb+B!(t zKYb*Fy-S~vP7fWt#;+es4a8!2ekRphzp=5o(7;$Xm2U2J3$E8@7Px!1nq2uxeO@rv z%vndtzQ(R|cPJ{?h{*Ox$9gm0vGpU$rdJyH?69sSzXt_&@$AP`{{AMK^iNgBhoP;M zfBpC_lGOZd>bGY-?T(Avm0~NC?hI95-JGAM%N5pb;N3a+s&6~_A)22Ifo|4yx9*e| z#VCYWfPW=H@5Jq5c!0m>{>_rTaJ=uv?_yWacM2Sd6l)pDx0+De*2UVbu-}%o>UPxM zHh#?vHDiV!&03D0CcB?FLts}I``;*&MP}=5#b%vXLTYMi*h863hWz$DaJC38w#P27 znRE-PSIumZY@psBs%2cR>;_-QTZ-`?56M@ajdMTz{jL7kGM)uk7P5GxU-o2>3D++Mi9^VBZiy-VA< zZcO&GA^iDw|2uG(h<9%dLe(r7CI3*Y|3Aa}zDpiqUK*y`9GL|1i)l1(*+Cv`koo80xk(={Jj28 z|L3Jfogp%W2Thm=Fw&=D#F*2@54!n!RhV@v$!!3b%Ep&g}D7lSA zlJSYUMe(a9wBY*S$NLVKvuQHTw!LuHB#)KqHJ;w7;whWX=1&5eq)OV`(fz=|exi=2 z62D}gzD7_0Z%0rJ~{E1J)y-XWIZ&Wpb{D@h*~Z(D_~(=k`(QBI7ko zB`i&&=%BwXDaZ?rD|gH>gbRQpl{ENgTz9>kHY~$wzFoQbEbI0?p=^WIQx0h~+X(*3 zY`jIjvALfR=uwqs1TIfvoHJwby6DV7m%Xdk*hXl01dI&_CNm@8#OI6Yk3vCxy|}me zRG%U|>*aS8ha8XiQ#_zYpdAFOZ{{~RyIp?EI^%QQs*vBRpA2cakgu|7OGLz(3_aV{ zDem{(#GXw2H66udaN`MnbE&||qmw!;?d1E-?}(bqf3{J-YhOT7X-XT_2@b5y0wbuFj>?rJipNV;nCuP zWI+&{pFxxsi<0^=uB!dO=)yP3>!^m_wSH~=T_)wcqRW!vbCZUknL1Zo3-gmhI84A_ z2gdi9Ocau6PJV51b*W#}y3x?ls+~LhVh52pD4=%d2~nZG?c?VgO)>5#;|I^xR!2>j z8w7$^C#IfpFQ`6Vjkl}^!J;O=U4}JWK3_?4El{x-Hz=8fk?Z?$CLwu;&PI<4In#E?|l_@WD@?Q|*?bcstB{-jd>%MZF z4l{zBOyFC$&x^I8Uz`Ltt|rZdkxU8wifDZYt(3mmR8p$MLN%$EBEM@9anIrbGK7nJ zJN9oOC+GMX(SfTu1Irn>=pk5cbOh8(RqznkCGA1>Hc;(iYunr*W55@`nUC5@mi5ky zBk=_mQ{=v=;HM!x^RTmHA+!mOiW!qq-DIp6yjy#E0qQik`1L%mbQ%X=^A&5(chD9< z*nKseK>SeiN{vU9iEb{uu+UX}^h7Xmj1Ru!w7~^V+x2L}^&{%Bs9aBW$Mmo3jpIDs z{F8a8agwW6%geaUGZ#byZ-bWHuZt$tQ153lZS^V_pnusZf{%=!(_ys{fhD|*u2B!_aq+m^r?hrbdU=rCdriweY1hPgu;&$^=dh%IhOOLdY098- z)`F|ux?!51T*+8}8oH2c23O;jQ#pC(719;&IOP#P=9qkbt);dxJF`ixQVS2cLxvDz zl%V5VHFsI6+b@D^vCD*do@KSKbwNOo97;qe&;#vL*0$F1a?t*@sKb~BzzB!*OEf?- zMF+n4mccKLlB0VMj|46m3bj;Xjz+b?k1lq=#zYd5qjK4n>lq%vnI3K=DD0U5pVni@ zzbrW&N8+|5*!F~hlbLjM^LXA4Lioy28(hAHx;`ue&YRE9Y)AZ|0RQ4Kqu&jX7t{HqW^3D7jDz5OW<&j~UiZ z2ONsy4zdp{wg%IxWts}8nT3hZe;Y6f%di!9Kv-n+vn=_jmy1z-T`%qB2Z9Wwv8lxF z(BIVySIm8SevWS`noFw6IdB|rS;evvqjv($xIE0W?FrqqtjcICk5oQ)zT(+CV(rDA z-N*fs_t*$M7kw?t;i^qQ+kYByN85$E@N=x7|Bb!z;NwbXvfz$GQF3TKj5D?D@=7_I z8xP$qsLp$dRAp6{pS=7&(z2e5lzrC3&n=q|Cf+!Cez?*~#N(imciDN4VQWj$y|M$^ zEyoI&F`x4YTRDdBf(00QX!IP|G-3rKUG;BmGB#YY6hfWXMZEMfV?Fw2sMmi95&7Kq z-8Oxye6A9kJCR`$;gcIgO>nkIOdr=Eg1kcLzV&KlJs*+Y2!Ui{PkIH6(dJU^9rtjjig~4O!ufAzZxd zD&Xmb@_hh^!ZWpuL4@Hcm+>CvHCiu9S1!BDM|Nu$)`>DFoSv8;Y)sUn%rcx;xB zSF{{rwb47u;h9Lm<=Xcy8;x3TANEGio-9XeFRS|`+jXSVfArI`w1 z3+$DNWapT$dSSh}BTMXo)n=r~If%2e&iS^1Pp@`Xs>GPrFPKA3;AGMx+JU9l6n zZ+*M8ndsp(H%$nkOm+cIPyFnGve!D_SiAd#h%(7eZKm)|Br^hs4BztUrP{fyT4af} zLA(9P^s~aHF-|MhDlUXZi>`_St^L)`mO_te38j3?8bSH--qw`X+MO!qmAEhU$VThI zpxV754nq6~Ys77YuEND!&Nx8J-Pzi{^)JkNy5Z85^h#-N3;l?xGRgeTw(A5QXMvG= zfV0SvbE5hzIhGiK!`pCm(cp8YFC|ra%$G40FBr}4U+Li7uDka1JER|X zoB`EB)C?DIU7fEjj_-c$KU-EPW>GAlBgmMa$giAYL*sI45R~8l?zNSV#40G3Sr?U* zCe6AXN~fO2Di52qqYlGwfH&Cr2{@~{RMG=UI-5t@o}D+>tUJ4a)^0pZf1^& z5%ONT`z^^l`kxrr+tcu(e=WpZ42@#7%#PWbsR zxtD9}H-6j!{u{hJDMjS0SckZUu6m+FdkCwIJ`S5}eWOxe&Vk;&m)&P`&XHEpy2pO8ENW(gU$Tu98r)8)3Px$01{ zYCH=xPvoLTeV%FJm9z2IRxEdN}!-kuz9?G+2{snnO5?^w@FWM|;K&QofNyh*r^F~;j5D`wI+5Aw10FbNrDEqMGA zmdPgp0L&6mwHO*^n|1>Z!|Ilb#36K3rGWd?4Ayqxx;`J%-VM#kip%XAS}HBuT?D&- ze#}Cb*p^HT;mJ(Cx{$4Dfqk8J49SST0%>6~qPm=AthUL3OPu&UkT)~>w2+r0?=i^h zfykSW+)Jf7f^Kc*hg<4tWnab=RKloGpC>|{5+czMh zkmAVry7m%rXLU8F0^AT1D z4k;6?cipmoF{6Q(m*;IH*}JuNY}42=@NQ$ywzr)&Gs^Y#yd$rV)h@n+YjpuONYXSq zSLSLLT(~sf(Fo>Ed-=Bdh=f|98dmQoj4Yn@W*MM`Os;ekW-N0464>202%yPdmN-7M z9VuH#P?tG%N-MW*m3B|0tD8=mN6%Ot?DqN#Ogme8tk2Y1gaDyEy#O)$r6=c(_w4Gb zR}UxoWR&Z&xM#km<19x*)cc4)14UZpv*p6WU01Xzayg&wP=PbHfy2RmjXp-76Nd@= zUESdh$fBdbfYOj@L9t1_xxGun2|-3mYl^ZaK~Acnq!>t~o0b9pp@8Z_8?$cnWbr!A zWTl;C;3#@muJF}LEe+t$P)$eGw#2I&-z>sAW8{DeyL9t;<+EXKXWQJ5s(A0E7Sl1- z_U6%B^+E+yr|Kcq#S&hTIV=lGlRF8Hl9NqY<_qfFq9JY^>>U-NGGd^jl7~t3e5Gll zod~qV;DsE{xzA*WDfr6o%y*pcuuriRy2Mp1*KZu4#BIv$n`(QUDH7>Q&v)#)@47NC zL0(EjBQsJu*eXf95brB0xsgBkC9@>|-7IBDdPO=;TkCbP4Wb9IUL15X9`4O5Yr98k z^MLnai=hXdIFl%pKEJ6hnnO^wGm=*m!PfPOjx|a(`Szd}HizBp0c2=AObm5f8&zwc zXz>(Mc`w@+7kWc4pBE~{LZe^;dsYO1S93;&?AbN2nsLZ>oiaN0xN_RVs8pxnY$cxK zUZS-P9n-a2u%-FFD=2%v#*`sY1ZQVdcNX8WK3~Q9AQh$OLo$7-0_3P6TCbK+4Gp7$ zZH%aP8>@D=LT^Tc+fM?4c2otfY(0@fS#fk4!)dLXS2TdL{ zjJtWF%_HYjazvGA2~w#jlbMGMxg8ICJjuGAcl60*xTeD`xV$L6Zf{D-kuw04(RRb& z$UNFFsiC{v0GKq+Tp2K{h?fTepKdcBO0hn7Y6U_YJg**p#)gV^C`!w7Wo-g`dwbM# zGeF%R1bocdSkxw}&w8o8$cRYnVt0Am-*(uE&Sz!R#o6?r1#s(&wJ#6Pz%2x}T|}@c zXL+m&ft`k)IO~BAZA|oQL$9|zD&_-2b9+9Enbqu<8zl@=%OOINiiYc z(Xbo;vc4VndBIEz)T1>e=R4|P zJkPY;_8Xj+JHlV{au0wd+mcT&PERI_1tT>nEZ_dZ%6TUJ4g$`o6|tDZA>URemnSi@ zs5vUl_koD_p^U(x*_9{^wU*B?wpxd?^hgm!9WToi?7A?&1{4PtpG|C9hS>HHegexx z5+VYzyoc6#m*cEEBm0zo{G|)>aiU$v6K9c*vV7RM*K7Ka;iz!f%*E4zktH9RfQ(+y z_SL|f#T)+Fq?so1W3!!l!MAMXd``2;3y11@)K>sIM(inIL0CtgK$skS6nVyv9^I^1%n4#gtz7QtF-8O1<^ zCg?(2P@?2vi99@Gy=l*U0~hTEgEgKXor^2V49b2Nltm-^6W8ju%ii}N=}q5?$Dz$; zM|%>@@7nGYEvmL@M*!Z!EcU=@-riZf@g@u1(R!L9GkUdbzLD$hRU1X1vPGXbzWxPI z8pzmo0?rrxq@AgxX=4XltWFcL|KjUYcm6^wx7zKM6zAm{sBmHD?Jy%SuKyIMZMK=; zbz8~UWG}X2@3p#fR$3XdLCPSYR`wv{O%R7;iozSUG0aNw|<- zDJnbx<#EqkT$?4r!?)!8JVu$A{#7gY1m>oMV7nX%PO=o4{w#Dt?sH3?iit4ZGS2*^ zhm(5@Yr~rrF;F&h?3DAx@eQg>;h4S=Q@d3m;{g{7q<<(>n2U~(iGoOAr+)(=IZt+T zXbmqYErEg*!k87`(M{*p{k~A&5}Yn&i)U&YdR7(B$;@B5@1-;ZixIoBG$g#wqwb3f zQ5=2z5m5ubL2u@CI&@%etA__paWZ2&u=@?b*zjOzwF0}&U6$y93e_e1VHI}Tj&ORw z!KxT|Yj8fJ+RG+N9txQGqXYmP!tm;CpaL)5L{I8w_158SK)DV_aX*Fn>a8v;7ebHT z{O=Im`Y0i;T>CkMB)Zuh#up=Ck!U{>06%#$ri)a;v$FK$?^&XM0@%POna_YsIE`v| z#a&vUN(p0fyGV?A&FSlvYm39=h$Uj8R+^pb+7WyKr6<@RN|hxMCsa0#Kd8I3PanB0 zWAP>wMebx&H)Bk|s=#J+vt-DQroqYV@X2VabDSmsfL`_W3@TI`hKte+y>@3KgUJ|~ z+>f!`vo@Q_3uUZ5-*$O+Vw&{4jz`UzL?yKWXd|chcQc|yj7&cjUh(Ft8?APAGCj)_ z(O{UcvOAX-C&cgi5^UWpd#n!1qOa=3JG!{1o|ff7Hse8A$ylWc-Zm)S6NDd-NUXm3 z_SOJ7AoKYaP*)38IP5J;bea@)-kI9nyi#s)U8-+^=P=Lm=_;ps58h7EsxE&+VW@#r zC7$xT?h^5A7n#qG+)EA?3a8GC5e&>|15jRk*Ih^PeL36t&Y>8Zt^8?lxNeMX{&VHP zVdV=0y0X6a`v;wct@1K_k8bd6>x3VMW&vhH2^bo|2K$Rb!UiqV;}~Y!S9-JIif`Rk z6T_TsZw$Hgs5T~WrG1L)mGc!sbZeyYu;pPw#T(+PHiqK0RFt+c%eGeAYd8KKh^dNo z&@yW;$to(%j5c70?$Hk38Nl0Z*!`+P_oal(W~tU${J7DNh?>84KWZpLQF745tg6u^ ztm4DfT$}1NnZ0|g`8aSW9?AG&FEEP&y&IxU8EymGDq-Jw`41RD;v3L39GHg>O%fN%%QEbcH=aAD zn}0#)UdmpH!_(lIuS(PX>LOj)V9}SeBnis4F646z28?rFdigvESt^Oc=?&3Cv$2O^ z6{Gy?OM{CAuD%==CVO?W?@^kaZ$bmbo&hce8UVb`vNTd;k)#!3j}bpH04Td3gwSUS zRis(Uvo-<|^%ZG5rz^V#B!RVZ;wQEkO{@&%L)`h49DP-_xudgR+m%+Wx8DNBY9p{W zHmh}q<1BO|(DE$C-Y%eyQROVCUx1$OhvL$@nZp2jb|gT(3KBr8|NOG5WZ!FGw-;eG znGk+X-&ghRuWa;xrPX9U{jQ?APVUlP!xzAMS(+y_J(r&Ij?Gf6@Xx1wiBs2Ko24{D?G|5N zZTf2A1=5wg2`@&*O#;u)o+S_g-adeN8%>a2e!c?>X~EGFFoQW}JmS3Bs= zUyF{ejz`rgPsa3CV_XZkBpEq4Wz_k#ZMTE1;i#2t)dEkr7Z+V{D4EodDI7A91?gCFc0G!dh4%X&#FkODX=*>#cbF$YP|t6YAKpW zX9K;SA3Yx3CBDhW&5Xzuu{^K8zCvW)sz+SBNq*_Gt|r(D=f1C=$ZhavEX`j6Cn}Oi zi`h1I*wv*afg~^LPWYbPAkcZm=YhG%J;RUbFjuDtq#1sMo(s+BhxBS_#)p$xd`FA@|0OQL@Y!8f&&OlL|w|Ho0!E zF6v$eqp_5XWf-!Io#;|TWFKoCNrjnYAIrSY^n1^H&g=W_oL=Y5Ki}^>^L#$fXWt%% z#Kesa#j}hb?C8as0X0SF&mYyYwA(Qr5n&7JoX^+CMC%caP2i@2GGc-G*cW~gn8<06 z$q4<51|_thg$|}2gHE6Bl1~-ZrY(n07go5xuiZG(hhFd$+ZtFwD8`h$J)CCUEIj_Q;muK;+_Gr4=kaclM&G=MW&{zi@!!DU8sO)m$ z1x(f51d;R09K!o|yPG{9ULPFoSupqkzm~6f0%AbxRdVr>vKoGKn9>I59&b5+_Zay= zDpTHQrfY}WkWY@!mj?q*M0vs(J|pzuO7D%1K8XsV@ba!5+#f0%M{XmXJ_HKKkDJxW zOP~jjIbJX#&9|w9;jr6kKbIwyLFOke#84%`qO-vq<*TdrWr;U*CM_dS^FtZesT zJTnDn!&{$!Gnb>!iP>S8uETAad3G zL>B#8oP~?fAy6;AilmeTfg6c^g+i2yev}q8z*Cl%SLOa6P3XCRM-E_ui!32-yZWl2 z!X@f2tH;@`upBIFg#-{Q--nw(kd`=@Ia8UY58L&rUIqB^WOD5kw7nkjw?I>(&HIuN zMK~T0dB6wO0apZV@aWP83o#Q|Tex+55d4v))<NFoCEFRU zdskZYVE&9Obr@FKt(y6%<=S6p&?aT8Isp@MUyY6@^c9~QUxP6af@xq=B0i<>nKP$j?dy?+) zM`NhHk_ZinZk#ul`uS=Ns6@c*s&kJ0;_%jYf2%1jRi0RG+6oUTT~79QmR3K@5gx^E zKt-~+_HhU}&#sB3SPPJC+K7mL=UoS2bGgR5fjsI*eh`Pq4(apZ+-6xfmDg2VR9yF*ImyA^UoFA&(2S~HmEwmuf_wtk2{=jY3osM7wA*4 z>Uh+QO?NCW%v$}wq1FGKZ{`p`<%+-1es}B6#+h~`>^@cGbgjeAzVGyd-2=qBAaoMC zak;Ej+`DEh)kdWtTNj?tM|NVB?RDjxj?THVE5T5MZB~vhl$Qb?8Efy7q~E-RsTBMZ zPG5joO%QYFHmg0AfG{^gN}x~FrGQq2kfKkkz!UwPfSq&!0`cj7FN@a#vPEtq!D34E zDbx!DxcsvFc=K5nM!LYUiYV3d9$LK1D)u!)_9rd;U2F?Zj&noZj*F*!}i@6 zx4&=e8CJsBr+lZ(FUybEsop_GMe-awz<)1^RZueXwPoMWAZ)XwyQ)GdS!Eowb5G5* z?ku_=kdyeKNDU&He9pmQGA|Zu(j6#$^a9#FvIx4PEk)hcBvvNJ&7+XlL^0aBDpQ-p z77`~6_&bD*w{EN_eVEkS`ju~bJfzw<%Ecpt!xSiLahd!Vu#75x=O%Ik`4*JIgX+C* zUv@U;K>8d~{t>K}#|=t%diz)^OqDvOCQL(7<3CZqD7zuO+>9FQP*XlLj(c;`j$S}- zx<}6Q{FXWl6)y<&e{ZItL%+)Mt7o|naV)hz;i*tQ?JYA7`eT31gjAe_>n(%QxnrTQ z3ThjPxi@yz6IZ*`pPO=;ZmY{PC^h9M+oMqfO5KKUS)DT}Wha7%O{u+f)Y9&Wn1p&J zuV9m1wl|n?%~`0iZP|!xU>dP%*{(CcpfQEhVn(A-o=}I3?;kKkB<`$3J9g$M=Iy$ z8qKmMUTKWC^x7=O%e>b9>xReLzzgZE^d;qsoLb+POIPS6PoP3(%%R=cLd-b0qhFl*BnuG24^AU#v(H|{$;j|WP5~W$ ziXinSF?VL%{L{xhHE->jn$@Waio>z3U;yD#?&>?=#E@*Tc1L2VSSM$H*wIR3ZQ&;k zJ>eU(l`EkODWPkeGXu6?ZpNc&_w#6<4~K;;$5-?D1ceHXdwoq*3G^s*oKQkhq|uC$ zdhF!NUJb%XrSer>9m7o=V##`9o?rw~V1ihSOnOu_`FMloL?5q^&P2B1V69n~mLRRw zgsjDL8B(^@wL|pfT&~|2oR8F1L{ailgptQTflTd6w~>9$J@Q29ACoJbd?c-n>|QVR zaN}q)UL@VFY$51Vd{GKiEsdVC;-1Z51mjM;C~CLgywN8%jYGid!vLhL((e@fDkgb0 zWmKQGG1hxKyUn(+BnSyUNx29yC1EqKd^?)PX+WRnVW@IVr5at0ok}*(K=(%b9r8rW z{lDhWxth@`FT7?IF}iY#oxF<8`ZFfsXSfcPGYL?GwscE*?*R z^Oyo~#@H#_Q+8S0ZcS<;D+0?WjHa0<myrLt8 zM=$!Ff}*uIB`Vsp>_B-o<{rp9Mn)U`loNYRJgxmS%9E@(|Czi+kOhjXwvMD9( zBJb-w_fno0Q#yF_?{GaR&I+XfAU%w3oVh_(oqJhD#KbaZW+U#!d>Vw--)xJ6#7nvz z?RwqUeT}6cQ+}nNXEB9-9`vZqmZfmy=-X8?&Eb}*7g&YbZ6@t>NYG!_5J-m{qmm+3?MLMMhWD(c~ooj5MFs$j}7~T zJBbNR@!4v!7elsL7=ckS*_j#tA^!*>SDdPU>+(CN z45stXX!_}S`?dy&iMKZ8BW=7O(92F*Ny zfncwl?D$s-7Wq8^cY)&t)G7~L+S?=N$Pk*(3XFlI@{Ns42wLex#pGr`x2%6`WUXu}9b9L{Ml)c^5ox^0kCb^wC~{kO%j^-rNbi}M zSphhf8y1$IHO2Yzm`l?iSK>I|lRkwa5cIrXTn>OJx@6&iGm?Y-F@c12=E%51M*on- zcy?jf@KBLDfw(5Yp1%kQ@xNsf`oL`mXw0;$&Q^+&?g<414i^0{s!rSR77fe=pU&Xu z`tOWNWD-DN;f`#-!ppw1(aYFEXWv=8bWYdzY9+n= z;9!=KMuE(aI*5AvS`{~MAL{C&c$H0#@u`vS^ypC7kfy2cRkCDOxtI5M+{reOEkU-t zIR(KuU*u!_L1(Y@H%Uat=^h87Lu@}cfLS+kr$UENMJ$IW@U!<~2MegRo9PhA&CLaF z9anEHwx7+x5d~DvnpQFU*(w$Gg>jB-C;Zm!|HB_v=lCg^QgKg6hU8-+2rJg~=BfSc zS@3f>pV%aZM3-a`$D-~Evaxrv#=}$ikeE!YrMZ4PXccu3Ge~eN=C&_o zooN!pVPF}E zwb@&_%+6j6RMIK%7Y@5xARPPX!FBq|rWik3w{HoL6jSL0dMv(vx#SODVy(>WL(D&j ztO}yJS&)$~CgPu<*&%CWonZv*dr0a=kSnh*%JDLlTf5UdT2M_iNjK|OX-)V$BkObj zSIXxPS3fKkM7gTIaGy+}khf3n&P_NZW&3(z>GL+h5z%wn>)TxZR4qk`(_om$+>(m2v7e zI;GwAmbnR2H4lX7r*wh(!>H(~rw~Ghmqee&qo>Mj2#Ssgj3mD%_wK!Ll7o|6dvaA| z%k&dzsM&QLGh)>r*G+y92j9GY>n7m`e$o?`H;>Bp8o%63dU`9N&0z8x)fYz3ZzhlN z!g6k@w$V1=>HZL(2@M-0k@|TXGf#Nq-nFMs*RBx`J&(BQ_MO`0>C7$W2RBLNKgT?K zK&vSC;5~!>`$zIGV>I#zrh>KZhs9WS(JtK{4xW*3ijiL8*}K}2BdkR#@`PvbLy<(! zi}u00?(AuyHo2#EtW9)0@}+}VJ3?QgmN%#u5<|&rc;v6S9D@W6;m zHPkSIyEAdVjS>A0dj;k3^!Y@F0%2J84PfBg?KrW8S@Cn_=*<{V$dA^YuQ?~B}XMj+QA#Q$6k&RjnS7t#vVGXI5^enJDfULJIIe# z6t`#;78w?~jrweak8zJh7td)k51QFMc6erIWnVTtS?Hp;*vPIp@>ED&^OJs2qvn2@ z4S*2NZ~gkNf2V6FZ>P_TXzEwJ8sVjh722OYo|GDwni^{Q#d&5NNp8Q~jz?xHGmO0H zwzd(R;HMBm^TQ&9?!uWk80uY(wj1adr8gobc1Lb)+}RvmpBX>>+&fG*+COMqI9+t6 zM**?T1*m{3P@*mSzK~AG$YVMLv#I38&l6%yQEMbP;er60iP1eIzHx)>4Ot#hI@thS zv!E3nhPHqn$S-LWKl%vdBx0_iS*xuc|OM`#=9u^do*gFwksOhp#9Lahv z_JSwEA>8H}A__%=W$l!)QR!>fE7kLHa?CK8iD=kph~CBD&EL%=p`@f{Gg2H?y2ByL z78|z^=gC2)Op(#*;)}SEO#57Dr>`bM478H3?^`Wso0(BAnhrQq5M&jT_A%YlHMs)$ z2#EQnG8H$BSp5muHNAd*h5kywQ;>P_7r>ZAt?;2wnimpNBOMDVQa*UucT4yETwYin zNbNG^R%|7QTr6$2e)98ymjmMLLkU(21N{OSLLk+!Q5}N^+kHoUsFYbg()jHGSy!7C z;bjN&{vqwg#B*XF-7GZ|YgA#Qi(7QxND4=)mq%;=dE&m`{@cAk{UFme)4`@e@A=^n zLPE2_!9{));U&8JlgG+y~q=00_{yxW^jN_L&}IyCUwMNWZ2 zt%8obSIET2ZJC9@JC~EK!#>L^iF4ssJCco~EiV z-KIGi03c@vp|$*4wehdEvl^MtSnyCTdN$mfvjK_kKo4{ z{L-&{G|raNG)FZ<3hxx|t5MV_7@A}%N{q~kLl5Vt-c{ERs7OqJrMJ#INM&gT>MEyI zO%GbV7vfg)Et6;Y046Ri!>`Ad9k38y*mym(4q)U49e1By^mT(TMQH;3K^cv-ulK+4 z?38oY7ov6=DE(GZv$S3kXp$W%Shmk)|J!Ebw-lsIx0tA8bOMczo?R-AfyQBD9!;KE zTi4f`Fv6Jib|Cn;cg_ubiPSuaxF{=|D5}Raj_gwg$OcT9DhCejYhYY|Y7a5f1v>dS zA7a+B!GR{*YHMhp`+m9J(2dL;s1%x`1;qHC!F!K&v;7BrL9HqK2<&+|bHsL`g#IxD z$%8Do8_w)6YJN;|21$S zw$)G12;ZU7yhvoB29M$U=x4kq{S;1^$8 z&f@Lt1auSkmb&-5hd8eN>oMOwmfv069i{H+si?Eafn2RwM0kaH`R_?zXJKKHbhWY( z*Le2gkKwpqQuplK-Cv9I@p*Z9@p=jIf?RF+1jNL|`1l3+1O<6;J$T%FfbQnrJV3Ym zf1Bjbd7fFjS-RT4cDDxsS$@rHZUORem%4ZF*Ft}P{cWGt-uC}k3F!96v2X|E`}Gf> z053n^-{-~+mHhQoT;1N=+DY%3y|XpY4Y!80ps0wbjeLFqQ8;r_fs6bq_0cz{hjvG*R69^rEu(Euz#keh5IJ>#T(p94)=ce z$2YD`>l66wpcVK1T=AK#mN)*^EJ@9su}tD0mxMDq8~T#^CUP)c_lb$s*Qo7@`lPd2Lu^R{tOBU_%J&^HKEai1H(8zp;r$1VC)HQ! zuJETj=imDeI{!K0r$;P7_ALMD62C@q-MQITc2n8of3UM4yaIv$>yy~a? zV<<*RNjT=f0wu`9Ihfju|)p z2Z#P&X8eb;@xRRYkAeHYlJTEvw*Q~1sTyxQH`Mvng#Si+maq&$brD=;*0Z|iDBIcX zM~eTVGkN$1krVv{DLiw9b$_iNi#|SaRC^#YYmeVoa4(DUpCz#^^uezg%BkD7P%USn zOHQVLZN)_He|bIsZLhWN=$VG*C*dG_RAF(%>LJ$`_x0hm$x6!>Q8nm4Mvq25G5NJM z521I$@BT`$7U>2zv&W_RUN;k^+HKCd8u!zBPwhuTmY@Fg-)Gu*&H~w7p(Zn{(7PoN z`1Oq|b0dFoa!v{3UkS<+N76h>#TMVAh|th+6sB-m2pt~{Enne?Ve(oL+utNKWdA#@ z291Ib&Rc3B>4uMk8b9A@^DlS$@hz`WPFCtKvDMZ?kgf9I@ZnYdeMPg1hiv@)XJs>d zS!4B2d}mTu%h2F)@ju4~V{R%S=KKzwW;bo{`!IK93}pX>egAZV(aI+#l#2Qq_Jv+VNtjK#g?l6n{9m#4{2msq;{_GhYwC875?14 z`X<5pDHPA9{5TK$*M?b3p9S(E&q?SCe>Gjt^P39M68L@h4(dd2|B1lSrYF7^yg~Y# zQuddBEd<)sU5@uSr*Hf}A&m!Bn^CL9^GA9=4H`j4DWjO1wU>YA!GCEyF(Fugrh&+k z`m7=+#|t$_anN|u_rJoCtIus^l0;PHPjWr^l!~L5pQ9-NkRV;&@HzEN&!u*`R|&sw z0_S*yR{tdd>lKPd#BAQUK4MmS*<|+PB;q=#{?F>=4Y~SlRLiygu^0bPBO*L8 z6CQ5uABS`Emqg!@?k@Kx!}k%eyU{A?OhPu2l;Lw1Zq0`)hC_A6&`F0R!PtNbY+=W!bvOk(~a^;&Ab)O-_} z8T;4XGiL9H!1JNN@9Ft%)^1EvzV6YBFPIq5(8t!YeJer5a(@@B|I(=W_)CjUb&{Cb zh$MuwumtJ9Ga3K;IfH#~b!|2^@)D+0ul7Z{A?WGdRtLDFqwxtb@GQSArnf{p42oS< z)1tDA!mN5ZmM;~00qasl)eq+5S!{q-U;=gK# zPock6aom5ql^ueVXi3aj!|N^U-647A=gGX8iwQ%y3*4p`XEu@XoSIBgr4_BbDBb{- zQ=4>WI+|!kO1ZF|*)nVGdw_HHR)D{Pe#f3ap%O}-hI%82VN{> ztu>skxWKmo$>@Sc-p#5Tf10oV3t(mezp1=ak7uJJ*LaQKmtM5~C%s4$++2~q$sTmt ze_y_HYszhbnS7Fu_wnTj)T{#iqrq$|fA_~*SmakI`Nz$Q%!by|YRSJ|EAz@P!8p=yVXo{6S#Vl;Iatra>*7$QpaiM3>!NI5Qj&{aAFR-}Gj(spqRLD0;A@%qu`w z&~KnQ<#f1Lz-#AxxRocuN(SmR$BqF`aAOj0c+xg#uJ2@TLKBh37ZVhc43Iu>?fKz8 zoWa9xTlD+Cx^w@aPw*wpZ+_qtr0A0^-@A6rj5;T|HuldBpG>aoH32Ka@m9>k0=Z2B zJWL{>?oR%@;eoni0s_`O?JgG~$`Qqrn6uzmx$R_20Y;Tn6D< zOW8jhox^*-bWuMszp1ym4TImzhsrS>!%hhMWwZM#d;^6MAd$LQ3?_y{(XBM~vwOLd z;4^SzL}RoxW-i6Ooo9EW`D)}edf2CQZMz+)LL6~0CHJ$WCWmZ7H02lPdfCf zM#8vX%HmZ&lq%2sSGoN|qdbiI?T^hTk(;TW&(~IZ4^3D0i_R|OQNl834;*?mnJ~tZ zn6=TpO^&SBMo!Re(b955H9qCm;|YNPOnj-6hU?oX;B3>2i3($j<5?nkh>4VrK7wz8 zcM#{}ab)|7@3fww_Q)ALmfla|pib{)(+x#;zWWfr5FagLe{O7GH(lZEq@Q-SIo#-W zus*^ax>YOhR5SEqy%$^;*H(>?W|qND@%0)`2g3M7&WL2aE|ykf`rLxdAiPJ%8Au4fcAt(53KX*7XXwD2zjRBrP0Jm==EvMN1OCPSV6oS$_(PW z0JBU=FU^OR1U_Ao?`FozmuVGVQ~NLK>7R9Ju*Gk9Y6I8tR&a?1(owrK+FXcOc?B(gp ziRGg>hMS_K#9C!8O7;qPVOyUkz2x=)`CDIRPUwtehBDZ5*q8~tz# zuvp$*m~Ya1WI9ajHRGu%_PDifJJaXLN5Esla@heEco1x-ixHKfAlSSggEjn_eg?jk zDPE3UQP#XXt9-m)w%?PEtsjwxe=)xtZXiu;zI;F$30sJ}EAEc&TpoFPbk`oklsvv$ zeR!n`TUl3rv@<4D(TE}Dxm{p5U6h>tDDC?WQ9Gox@POJ{CIx1kenbW8rS!<@wC(%QJk*!r$@ zFDg23XK%T;*Mq~zMRuL?y7PD)rpebBuezd1)AH{j;=eRLJ&2ijra^6r3xQ%mV)RXl z1f}$#W*46@>C>h7VLhK*1}o>LFpg|@|A@y<-eWM8ignM8bsrRd--E%JmbdFw`MnFZ zA&|hR$EQTFUbr#CEU7E;Bm%!?k1s7WH7;g7WR`7G*Uyc7{=+G2Rt(^7Ac4uKgEY5_1!Y^`1%JO@G2@zNDQR z@4ha|9;ok8YGH>gF;=r_`j>3i*hj|*` zam>5N2ZQF3h>3cZpvKlW9Y)eP-zkm4j9g;r{cyTvxhc(JXCx`})tpVKW%ct&OCp-L<0<@x%unhXj5M#KHwfU|yS zT^SO)0q>PY@1sWjO1s_ZwV*|_ zkS_sK<>zld7ogMV-^3*I7p_TLD9)Zd)2PGZ3}K{yujBRE2X3O_)I3pQZl;mxz$UgV zzl)I0OlRNv>Q0(FI-D_Hc>7=E!r+{_^5r$4ZU$plK*f zK9O)>eP0`Ur_Ctw)nWbO^Zq1?z}hml|R@FKo!eRg=p&vkWu$?)ZfyerKl z7>g-TyYCmV#MmZmVo{EbwGv$E^AV}Y@K%vL935E(D@)I~z?}iBn4CyS!jw*xXRfU- zKYzB<6DGkUCB?~^cOw&b8n6>EFhe}Y9L*x++pwVeLk~p^nwye966i z)(Sz^6t>uzKC|Ls<9d1|(oN0!Svz4_dsq6>He*D{ZMCAm#jWr(>v(%0wYpy{+s$Sr zVqfBtqZd{X@4j(yx@vkl4`<#UCcX18h8LodGtA?9u=Z-|04d&`CZg2T+?gGSWlJob z;VsMtr#a~z`!_Yea3$SF*`}QDBV;_QhT6}%X>BvIW*&WrlJWi-6Os8?lbi`7wI$r> zn#I;nHP%LF~G0>zdSG`EDi%Wb2Cs+HiL$L!vjLzFgM2pKfBaWs?hbk_;7Epba! zy+&b{@5dVZA-#`OEraym?-N{O3BvogAE_Eo)4mQ_94Hn}5-L2_v0pG?_anIM@;DBHtLx z4IeGloo3EVLu8+lCY{Xj4+exi8)=vbSx4bw-PgH8Dr)Sw)v`LX?*0#YneKR2ipVF23;M z5O;QX;os~NUgJ17HXvwc#@yKQ;&8NYpa#x*vlso=4htNx7_<-%(r?_@-doKM>@J0r zCC00%X2)wut;3eb#pAebRrRYe#fy)hjYyYSZ#In)gxidtH`l#AFg2$5XCH zQ)1R|3W?>w%d_dIk=Ki#z{bmE47Qk&CVXWwc_wMs?@=Qx%dz+6m#c<5@?F}SJX0!G zA5-3*t@eV+z*<#3tFvUVHNDxoa_PnrbupxTkB^wIH{%rycw_7fKM>h@1njMdAsDy= ziFh>O6wF9&m86T0LvQ~*UU5KvB2M~j^JyGZzmmG`d?{Ydy1f^IRI!^b2(ju-8k4@< z+UHv;g|v$1bY!>=h0rLFxe3%ix$xg9u)$o6h63589vf%r-D+sfrGXsY^R$?yG4*HL z1T^29L!ZckrGAz!^(Ife>-pH_T(6VpHXz1fS0`6632#0P-~OV+%V|?kOf77ZeSUGq zEa-*0Cm|Wu2pnB#Eg&fv!l%29#Yv5GPSnx10n+~I@x06>169l2%lRfAEi~>cUCK%8O8|1tvhB*2>4;rQB$lN=L&oy<4d=UImRdj2Cpk zmjo#WF{`x`sF?n2r`+KD;vSwGWi{>#J!2W?Q&%!;qQU19Rsp;Q4no4ePDmx>$3 zVp!*tcr0_$)v9~o-GJGsa`kAea$QLccC5#su#;uS^30&5@|Bi^xn_h?A{VO&2*xwz zxRV{Yn_p&n`LR*-JeLH)BsgJDI{jmvXN>Etm%Bx@pH zf-mY(U^p+gW1W-6X~9d;o98=F<}P|rE05pNR_*HjrkLRsA@yX4@z6b*mn!=$*;$P6 z$S%uX-L8b<>PP$EcXO9Q=_`~Hj1bS+mD3#Hx(@?e*2q}r#b*mk`(1waAAy!}dL-W8 zXJ6sN?c}sFbwy5%2lHe%a`2U<5Tod_{uQI2BjwrMbAgvU&v~2F4@CH&Wm*l%H|SPc zFM!npr~Rj})}6>iuCCKnnj2~3ez$#Rz@UL(Q~;Xr44vo1(Oo-{6z^Ek`f@MLd1&W- zx2*H&fzat%ZvWBw6Cu@(KA)OUJ%qHxIhiKPaeZ|INi&h|d~O6ro>p4{^tm$YXS8)+ z((YrkhK$QvDLx-U#a0MYyZ}zT5`7eHRBDeB-(1}*?A@)yPNVZ)EmCW=J-Srf7av+{ zJ=vg7wdZ=_YkVX$5Mu~xRP0IObXK*h_In%eKU%cC)u^{3(6kD1NOY%A&O|dRE_# zV}at|+P~k1F;#)ZfF{o9jUK6)!!mq|qQ5%*=l8u1!HwWuuzJrd?>1<5!=w?7V!x<; zH@KU+?c*Q^I6K--PV<^s26c8OPn__?`4Aq8_jkQowCX42^Lcw)GE|3oIJ|ERRO-l` zydn_7pA~?qyt3cC+i5slef%Wwq{o&SFdzPdWmQcE`^ak?h}CGMS?548Fe==H9<;Ki;!)9ESnPHQKooZ<<}$y@rK@y-#fg? z5S}~8-cUY~#{!m}c_}2OB_Z@Sbo*`mK1YqK%l-AJO6C4E)cx)0+A3^LU>vC#*z8RQ zCA;b_cUtHG1aWu>Y_5Dd_%HyS1i5=n24Fwart>gU#1A+qjCoc{iU{y-B6DzfUdil5 z^zpKRazl8eK$+isb7seE8Zw7}Up`XhKWiNySVFA70J7n@<@7#W_rLI z_7k+?au1-V=$72K$d7AZyk&p~Q0Kl$#qk>L-j(61=RX=0xU2jaLJeO)>v;0*ps%! zG&dNxWiH(}llOj}%Wv)D9#kdXuTGU9c?u;i>`w&2rp<{RDd&>!kUr?IZOYea^WWb- zR=F#ZEqn?w$d`bjmWAymy(QL=rI3UdWE&^Bvv@Y<@l5EU{K!)Z+6z0FZSOdr)xf#+ zQ6q3VNE*YMI>ro8R^(_)wyIk0~$3*`n^%*nj^GWV~L38=_;eNMFex#^$DY5 z!vM`>zso^<4Qvt@a?=Y@Zp4!dSFS-2ldn0K{G4?-!)cTqfH6f&P(a6W{&HY}8JxJ_ zTlU2IPupy;@Mo$M3$~zQ8aSxbr7(Yx%iN7AYo#);H@DRU9wp^;mAiZ^FIXxdIzMmZ z*c?6}7S?XMI9a3s-7a>S<`MK(H@$3}SR@MYND1BH<<-$@MIP1SD&+8V zWkIgjG-!Cvo5E!%iw4f}a6B{>P-m?Cc^YDMY8ifR$#Nj2QLKSkdVEf!EUPB@TkH%{ zzqrJ=HLB4G=_0}wv}HNwtUE~!i(tY!>GKEHIp>UKPaSy6 zie@6PeM1N?>Mx%Xvq)x2G~&ALaJ+a4)t}GdH$QwFD?WTcoPF_gAsCtsFrWI?neUNW%ACn z<;q9DjBah;F7iL!Q@Au?#CFf%t+c41MT3VlE*{t0UMwsZoW3vjR8LQe%-8y$G&2Og zteEw4u3pzy`B?pI*TOZLEO!eeP?a5 z!H&E+{Zkt!NDq1p+UgBxiPn13@q`@TzY6LZ|eBfRE@%8O+MF4>QnS6L>>2XsG8+v|{Q3y{ccT*x*>54KGsnT;@kfT@bD|?V1nkspqlj@GXK@UxOZn^K z9FF=!`D2mV9$iS5@%eKoZX-oslfrCN4%0QqK6*M&d+oNr67Qe&n&re<)!P2Z%|qkz zmlOS4^bkYn3N7p;lH5&hnC=~&)CTynS_=;Gy|`*EeUxRS#We7|%8=`gwR*kMV%*x!v! zsU%zIZCF&zyda}`{+`Nky&B*$0DSWEmga}kSE)i?IZ<^0sGZ(z5Bg?`RaNs!V4O1uh&m3?(`G9nt;J_0~Ct zZcNnn4{xf_?6kgg$oAju&~*icTgsw{UyvoHtGMl(6teb2W%^>~<&JHb071ngjz2XJ ztSxAH>_r;P>;txN@sPo8HXL!ad^*__7{78{J2q68F7DHuz~dLfY%#j>?ND-@)OA20 z@v~Ag*St#Bj|N77=R2*kn_cRR;#Sv3$!Ix2Fl>cP3#u&-ojKEpsB1r9|0pZ>;shY1 zau?7;6xl-SPRnEHaqu>6R+(*GVyB3;FxxXN(+Z6W5Og}RyX+Le?f_@jfS{urei8Y9 z+SL70NS$J}-!zi48J@(Wko>my%)AKny%ZAVG;-D6czzBn@etj5Sy{exGJ6caJ%ZZ9 zB}UZ6>ztXi#5A~HFr6F%Boq-9aA~t5QxwCOV646G*tJ-X3aM=J<0s9&E+%AU(V=^bJQW;ijbNVm(MUWcJzjBgQ*{y~S)oK_gI@E5xCTo!t_WNl6`JCZw2D?bq zDB)>$AIaeR!hP45p~TssmGs`Nw$YM8>>0&j=}?G{sOpwf+%34AE96!*T~UUqXx(e*8r zMX;KEml3xU`952$aOK}kiCgsj}?D)1W7zb8Z_Nn zDs%ak65i!8Va%xaet&{&chf5j9A<}$YYx5rEKV(CCfE8a;KmYe;7#q1{@~@0pX?82 zCQ9?f9aomVs02Y*<95UDK@FvT`ip*;4?R6S2;dNuJAeJ;)&?B@=C;;y*jy zd2qUyMI#;_uv2ckc5co=E;LALmgU4{p?Wv|Bzg;9t`m8vwz>Jv$DWAwFLIgJSYmkp zX6BS}X3lX;(7Xuz)%+o7y2e2h3r(MF3pSYvFh3ljy=}5@BEu7HPcqwJu22r1Xfgam zRh>NE@<>iun|s@!)`^$L@CreE&SpL{T=g+f53CQEcI>S44`_C;h&sb0DL4J)0lY z%DBUJ=3sN+dNtqIP0S@ND;uR&AB*XBJTS%;bL&WzY;oBNLBR8On@8Kzd?M&;R$5PC z@v|)HsQ2?a@Ei4IeRtYM55wyhJEu7etoKrFb-Hmuz&tZE>M{Bix240?J-31GZL+Fp z18ogblzpL!gCkDDGnvBBEyp?M`)C<<`2;xR%N7y;W{6gxXYyigMp^sJ^&|tSDxGcU zc3%CA#`91z#vcRJqiAi*iP!5J+G?1^nZUf4e8A1}xqgmkcq3=#1&U|#DpY;( zYSLo&h!ar39`$0AhjOyLlN%o_Y|yC7pOpHTHOxrje0dsk2Efd1u{Y1Plv1TU3>>#5~~iTc+|91k4Cb zX~{MprMY@GP>T&&a3C2LA7~0xyCzO=|HP%SQ&uPm$98S{vpB+&uW-fi8cXVaq;Ba7 zv!3qwg}um+TDQ|B}a zh$mDT)O`ek#lMI&)bp$-sDLt~{5Kh)5ckP7;+^DlV40mf6z%6ME&^)|P1l47KZwjS!Vy8%}@(-Zm)mQn)ShJ$&XHDuy=J3;H zrtYPSws1mPo4P@Q)0v%QG8;bu$|9p#D=YZhn1da5kIgG3oYVN6CyPYJbSO4UdnOiN8w=DGq1ac+YvTCn0cKk!<*|Tc=lW2tG&l7 zU{Ve^OJ{z)qLMYKXl+2=@Kx?bPtzgaG_-~(O@vKT2X>?0I6SE$hC&+iJ<4ICYRweg_&}8uW3`oFX z=|iQDQpfQMpjnnLjwX^{YRlsZX&Wg={8hUDCgE?DKK$JkZ=}3o4H!Rx7QF;`4Y+e^ zSG@ypX-XHcxi6Yz?2J{1+p)23&)CGrmu8%NLwbOzdT+H8D~)jhrmVNl*KLb+VU^pk z!g=H2d^d?9>KS13si;JsW7K46!n(;P;Amcm)7(YoyV4n)-L0MKej0Kexg2tVD<>8D zoAD|a3Xk3r541p7at7(o39Fng4rDuhVXq8&VlhqoVcu7u)osG$b1-fBJD8{$#&{(!{9k)Lc`0$A6!6R!ZM(98hvEM(hVJwtnSg(jOO z!n3`5Am?SQ&!twSFVEXfktN!WR-m;);(%?GotQM$w|!DAI{_-y00VeNnhP z2XJI%enrV?^1M-K+b29qt=lC%4X;3lbbCnZwcKbFqfFZ8pm}ZtM;%bSS!wmiRjnPP zs1mocD7gPOXr|z;1QQZ3Wp(m&NM9Vc?|4TQg@iN3hB0M#KE*pa866Phzaab3SEPZ4-mbk}?BI1secRZ(<-Kp;$)3?lHRJ$ZMsQV@@N_DHNA}koHv~0 zJl$HEIH)68sa3OQ4!=yJHm&)=+PD;Fu^^h=u+x#q{{1I(PB@=t#@%#!HtY(&aq15+ zV9R&tIZanp{{CBzu1~gs7pH}GcXi~1fL>G9`BoowG{bj$l2M|K<^`|umCKKOOnZ++ z^~(0W`#m{u87&*6$R~yhx=bR2k2J7nH~=UGo`)VH&c@bfuBWWuYIB#lFZnh>66o)v zqFz19naXi{~bYXR`sS{kr{Y>w#E3(p$Bn9x^VBz{82UIXw&oioW^?^(=dlaaUc73$2yov zCY?s{x7r;i@Z|-Tcqz9(`(^j-WQEq|)zkLEffPQ|bcvg_erDdL-9XhNIVc2ns#-8` zM~!}!)8zbtGXZy-0$c14 z1W?>&4kM#Y%(afg4Z(IDLv|i?M44iK6>|}VbtXluyv`ozXX`WknhiLOXKPpVGLv9<(IXytMt45x2%H-&jYDn9r77v@PE&$waB^nHo=y;A3-Jo?bg z+XqA+{nCj`x;g5jY%@KQ>|Totxu@>_&6(B0)1=^4(T=_=qI2*}1g5yUIqPL2C?-Oj z4SrH1B!dh*nU^;-@I)q%#7X&mYcqF9N*%Wk#BP7OK`Z?=+qgZRPWgtE>6qXJ-AjL5 zDCmhS)35F!Y{wwEvc%2MDD1BSV4x8M=-hAo{;L=NTKZzJ%g8o`N#+-u$P$fm*XI%l zw^EaYLx@uqHgkF|`P1#yuW!SwzAc3*=uH)cd}9j0+l-3L}2S@JdZT1tad-yd*9X%P6$m+dK92s zb34P+;7}=i+Kx(p8<%DdD==^hyDaI@DfW-&6clE0QVIpK^+en-s3AT4Qe)i=oV*6JAXFPu8WXSbH!KA{5iFnl`LS%G39fe zx{EJbs)=8Ac`2b){+y&HppUk7kiHTD&au6-Yuk+9U z-d5O3H|+AlF?_7H0b(DQUIM%ID|M9>-f%WSre1I$)Dyt!burl1AYp8w5)*hZWMhxJ z{g9~zQXNXy(wNR)YEW^!+SeXNp_HEvtSxoluGQ^bQnb{7`YJQO_?5y?!-+Ezyx;G+ zJ_34wezK^lWIT`%I#zJ+Wiqclm-tGoq|e@o{WAaAH|C{Ke!j+rl)j8zv(cw1(K3z0 zp_t}G?id+J0*|Hv?xN>?y0n?ycC{69gc|lop6Y5SN6V@7xn1}pBh0(wQKB0n4~taF zK|*XDa{-r@Q_kQmhr+L4V~>xIxQ!hSmCD}~XNsbYFG5S56Z^{8NlF$?0ACSr*%Q`0 z?8(eF&Y7K2T%^=|$JA7Mh=mTPkrn2^z0~H*uQt;V${CH?xEZh`RUmSa%&dt@-Xo`- z`1k-#Ft$ocEd%6!=Kw3{k-s5!#7uUyefd08=4L~?Ivn6=q*l?i=enIQ_wOnJzn`)6 z|8`L-Ui%XBul5-~G)Pr~rh`fz+z+L=PXBaoyxUpl%d-zk))zBRtY3hd=~2D$tCBtr z9rw+X>z79mc^>Jio^`*9u)=yNQ_#^X{I#4vQ2|7!_$}Q9oNJB{&Q;KYZFV3lkAdeG zgvf&el`povN&U>|!}ErHj-l&%$g3p=(zmqUJ&le|^BS$!7Oj1g9mnQh8_ z+u^q(&yO>C7k}M3sz}yRWDs=^0(`h!+mRzkkq)2BRgrP<_(n5cQQhu-$u|Driwva{ zoF`_OKb|^Z$Sj{`$J2C@%uM=pv|7-7K}*7S^gXLa<6h)WUfpF^?0t>h&W($ozk)`d z#|2)LOMi=m$^BojkAH8hNU2!t(ROrlTTeD|bs1cJ3tKpNruAdiOD2YQ)_2-^<9OzC z2*oLtW_!!vubV^1xZFzg^_F=SoIRaIM5fmypuNt`l1J*jyoxmo3t-CIitBz4?AWvN z(w{syg8y-~WJ_Gs5vhQzcck?UFr7L{J79hdW2C{%X2r3jL)DKvqyD%T2F?9H?ObU* z)a%l`tVlbjjhzv8B43c$X zXe=2<|9f;Es&n*z-aMb@&3WT<^BcdpuKT*~YyDpLh=Dyz{%Ce};|CS|Soh? zzhsv<5?|)sOAT{y@9z>)_dVv4dxogNX@MO~D2UnaIo2gpcRV5n)i^siO@vED4MGd+f1NGm-plnLZBYV`h!SD>p z_Y`VO_p9vB=WL@Ek~enedHL>S7C$Zme<8y7h#KrXx8HSfv&t2b)2t-5f|8QY(e?cw zj#$qhJsOYCf)=<|6!2yBYeHiU(yCf+h~c2`(I4DBoy*4)C!mg%Uq+KKhIVf2{wJT* zNJy=0PQdA7{1;<1q)U!dKeV>?9~x6BZ;su?Rxx)!qlDYdH6)IJlSC78W>Z7_Dl4yX zJCZZ}TP&2A?vH2$FVTC=Z`h`&P4%#mco&_bF;--tlyS&DC2K4Jt6L(^N<R)j*FE^bjLy z+{}j&l0Jw2utiZn?b-ZYh@E_7h)@WR@R%_6kn-L~z2)8rRn}~71;^*dH0)Kp&AbkqPCqobKTK8?w9I^_P2eOkn07m5l$bB7hV`6D z?Rp)}F7Hu$XFEL3pDm=z`hg?px_ZmzN68V-%dQ7B=0(WN5|#Lc@4a!Z=WD4F?vVYYrY!axfm1M zni}g0BnCEfHE@E_Jfc~>kZjU-Imajw{{Np>hqt< zhu~Xyu8!7MlPr)|H#xdBr|frWl{Vw1d9lS;d^UljNO?ol%sKY5hO2gn^1_cEhPk?X zJPXE{=D@fx`QV)Od!n?Pwe?8X-ml|4-JI*QY&wr6sU5qDO!x5G_W|`l zl$PwRqvCq3*CKuULmyX8=br9Ez7Ojf{iAC{N!~ejCJxT34IR(%2|as2pniJy)Oa^m zJIQcyxZmLO<*plZ9sBAS>+s`6CEm8VpZYyqwu-sN8$0KiD?NiHS`HJQ9(|C4-FSbk z0J4dQZL$oJm6BaOfa51@Qetqy8 zvpS~~AE384RzJ`~1!l~^pP9gIpK3*HQ`^NXimcCd$=)@AZm@7P^H>-~I~S494s>0- z-ry2bFTd;Dgr zvaff(_BEzX!au*-F7?JX)1w7o#_Neam*Zs2Ft`1Oyi=4t4!537*iiNSIb-2{|7llU zF5-yNRkfWZS`QH0-gqYciRcl9y@#RoB-+79Ezy5SOo^wzRkn9LvhY!;-ecVXd`UqW z8A)Uxpm%ytFQmWpgMO04Z*%6SX)tzpdA(!(c5ppU--!NR?xNtlc(dTb8KJTUfL>HQ zhmeawzm4Tii5}X--(jn6G_J7Ky~_QlMP+q!7=QT*x1E_CpVL^&*tuz(==B*n+>IaGXx~4=m1AaME zJGfD^EeQZnWUDit>{y&HQ2R!paZ&B|IkOMyUeQP=8MLm2+xb;Xg z77X6OaKZZzVT9>sjc*|DnI&BrcFanV3~myD&V07dK)TOTHLSFIOr{65PgB z%7fmHh+{N)E{v0lkNcBLiHc|ZE4E1AZC18P?U;J4U~bT>xMi+E4%a12n}Zfpx-KG- zhzdUt4P#YC)-P~|wGinfFUFk1gDy)DD-%^w z)_6LyOAOI$$#z}#D>GBSv^6DB$<>{6j^W~EfIg%?HQ|dgcZjt7+@=fdx`vRx2I}T} zC}>hXG$bVCY_~VaN0YMi@C2dgbofz4*tDeiO(O}y)1(6?*?r9dvH=f7v55tD1=i?} zY87EO_U{WAIV%4C(fqNXQh@VMdvP}Wc7~=?ojx+R*Z}wZ3!UOhNB03s+v_f6(lES_ zk1^SYR8;)PK~~N|S(Y4(M8FiYd|x_YGz!IQ%Rp5{(dk3&DZXv7#cWN&2Q(R=@cHn$ zO4+;_=@Q$|Hi~~lxZ1IPx z_@6t0l;Hq6`}*9oWS?=BnezFalM*K$9*-QGbGH}Y$MGoQculu3F!F64TmpY?v^Y?8 z>k&wv9|YmSFwEjtqy64*!_#d??uhU;LOHLE$fY+~mMOm+HEea1dI6j3;DIA)LSW7S zv`{{o)K7(ABayP|dRWxc?SarF9WIR z@IO?Pj}#QYaxUu_wSWam8CL+1CQR)~z~1CDA}Igt^OI|~Kh$;H6q#$L5m!#*?-Vh9 z60B@O`bf@vDDdX~Xo)GzIn@{&OtTNo^&MOziJTtZJw4jK0sE%K?@9aZS`P^)j>apb zM2Ti^j1wMAXKc+KhAp(})k0qtT-$O&FWwQiSJ~Yp$j*PDwFNZF^Ni!Rt05l3kGvzX z^JMW16C2hjR1R7hfr9d&-t=^--bsji?Xxq6)xNd2pKiOGhO;_(I=;=!fXC=k3(487 zWBY3x`Z@=Q|MS|%MQ-h*>^<)EQDo2&2GZjgnoFGUSUe!RVYuBV9iDOyy^qB{Kvv5 zwu3n;i}sIFhjLJkw$Dxq#%^H6Ez*;mwalCAYdyMD=h_D=&81q?uC<=*6ECbofKZ&q zFC7blEq3Umc_Z9`3Qvldcaus4Nm~-o^a1OcCT%`-;`GZ?)Y6i*{zk=%rHxPv(_*{n zHKf-d2vKq(6sKWrp|%7;{ARNLBp75p(Qf9{IiRH6e&Dc&zL!Ffah>JNaDQg!tOTEL z2>Q%Xyl=(gI)N)ZFzeJ4ATHsn(I0p|#7uHC;-z5|rzPWRKCRk11P?Sv*_SFE4WKxH z%tr@q=Gic!jTb#0`9`JOJ?Vv2k3rJzB6 zZhaiV3bsc?a_utHHihbkUGId-i@B0%VkUVRb)B1@Tkoo0>!5v>kxIh4;uc(B&W$lr zS&r`(Rc}2`S|8PYLi}b$K&pWw!Y)!p11}q=B8Rt;&W4aD^QP3*GMnrpjA8AX+bmwK z9kvfkjif*gaS2q2vx~WFI5&^9c$qP3VKS7l_?4EA`+U_XT{BQjszjo!vMqwx!(YL} z>8~U+kyv0$uJmr)=iw5Pchr#L3ns#_{&c~-p>)_5Fo{~3DQW+)kB|{75ZMnv_6ZQX zZ4t_h-6L&}eF`$;#KjmVXUT*oM$3M`F$ z16&slukKtldv9#LNeC7bh=ydMkDye!cx%E#s~VMeFT*gB|NKr8?U>5-jt#4)RlEnS zm)PXk6ENb`BD|56UB2I1uK3Q%&Pd#5hSGdBs%IiZFl@hJ?$r4uk9WjICZODfAyqW< z(gVTAoVXfF^@+f$Oo`sjfv_}QycNF`oPPfis4vQF+_TFoH0`Rnz1l?F5;1+>#gPOi z0xBq{G*}%si3B9@D-9l5d7a3izvOUeKFLITzz@#AYZ*IZK?j^t#a`k4SF z^Xf3iY+B(kFrI(nUC+9$(tm=(Uti$7D@4`;nhqD&XbqBl?*G zYo@Kq77r$cZ^kv*9$q<6yf;k)nRB%T5WB{4LE|02JM3@7SOvSI6S18x5WEoZ2frNQ z1Z|N=r~_H95PTb90Ze=D50jw;{)RlR7bThxw1UMh#SUMt)i9sEwLvxi7d*k;3xVN_ z-N|{Nsyqq?2j2G84ffm zpio8e(YBZz(>-RG9Jkh!67}_T>Zi+t-k2vYhlqX;-!_N+Y&x&X+!X{o`9NsGe3&+r z<%FT|^c?P+)0Z#sCV1=W7)+)x{s^pjnIRpuM~}ar4u{~^T^My|2sA}d)Ze!amHr?B zrZwG9q7Gi$Xyw#mSR6~<_ysjp&ST{?+3@XST!y^2{j%x)k)yuLV@(hU`z-S=fbX)` ztX$WDJ^=v_mS6Rvq5mozf6_#UyCec0N9!e2II<=20= ibT!xT|DiOC8#kQsARM1*lmYjmKu&6(I+mwpb^SltHm;HY literal 0 HcmV?d00001 diff --git a/docs/uptime/images/monitor-charts.png b/docs/uptime/images/monitor-charts.png new file mode 100644 index 0000000000000000000000000000000000000000..7bc5ecbad4a410da985695f5f912b8d5b50343e5 GIT binary patch literal 120607 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 LsaSC1_LKhrl+ed~ literal 0 HcmV?d00001 diff --git a/docs/uptime/images/monitor-list.png b/docs/uptime/images/monitor-list.png new file mode 100644 index 0000000000000000000000000000000000000000..591d94a5e49657ba60f0526d2b477969c0bc9ea7 GIT binary patch literal 212495 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 Ug*W^O&@vXu{xOVwI1}D*Ajr+ur8MyWF$~}!S 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 literal 0 HcmV?d00001 diff --git a/docs/uptime/images/status-bar.png b/docs/uptime/images/status-bar.png new file mode 100644 index 0000000000000000000000000000000000000000..0287ffd9cb2a3ffde46b5814c0a033bb93d13f55 GIT binary patch literal 34213 zcmbSz2UJr{*DivBfOG`uMT&rcQl(d=gHoj{ReBFKL_`6V-djMVcj+Y*73n4PoL zks2UCZv6i5{{OeuUF*GjLLZWGcz_(E*< zs&{2WeJ&wk>23e!ssEWLQGDKh5$t&d2!yqMs=_|BM8KYKulTn2sp&no?)qHelr{X{ zfY*SDmX>jjj;NZ{I|7s|YAV?hKQC3XMTP<{zUgVx64|ogiNy3K72X&fdL$zdmmATY zck9(IJ5?0-JzMDSF8ckO_iO`SD;rN|bL{<^b6*0w0NN%<&A8sIsZU? z@^UEqro9{fYsKH`dKKf=nLE`(+{4j^=cJW<5ssY&7aMBhg0ORgudP_?1gi=E$QM0-5F0nATus2NN%&oG~@LP@aMt|??=Yl_A#tdkB2R)wZ_Y@3Lf0*&J!~v6;~7-{a7M1@T_a} zo-a>kghT$>8;({+LACPH%Qpl;gzfL(&t%5ZHu1GkrYYUZ-w*Nrfb z7U)S?D)Ve;cCcXD&=9F}B?|SYuIhYZ-&b!b;2d`t4;^JtJ&MlU09FoNge?M@4(XUf!O}p1v@{J7!#kp}_gMU@3g^p0l(cUqiN;mYg0? z6qskl;v5!>jiH&2{Z-`F`-jL#N(X{@yHXiO-JJ~#McTGC>0Sm7W^(EG^V z^Ik}gcaKm{;IlZo7lZnr%Tub1zWOPaTb5g!8w4i;vQK1@n#iPiur~9=yMB8Ik(oyn zqNqom(W3WyS$Ub8ye*K;Oe^x+(KGuKRNJ&WlUs|^XI}@$$tH(KEsGaQFfS>p9rGo1 zJgVRl?T10tJuWe5Mkt%L?A4!BqVtlDn9$@a{7dk;$uZHLJ7n+33J9~vMi|>f>=@4( zikRFV$=c64{(5xqn3~D$k+j>lF5*n`7d2T9=BNPVe(x``F=F z53pYU4Fjp?$Yar0pb7F4tAc^hw~%s=Eh`M-G}C zrOTG8R||#8gFAXUWD)#`;?SZ{{7zVCyQ>R8I#>bI&>7x2)CtGl?@g+UnxKA5dYk+K z`5TJKJJDnnw?nAysFUdoX(rirsoU6_x!+S#)71*C3eCJ7+%WdRsKAuzKje_+e|Q>c z^j?mvi8$?pq@GgodtFn7wK2oP(!|mjD#{-*FWL5=jEjiK9Gr?R*Y`Q4OyoS3dL|g{ z{MkVj8Vjet8A_S^hH6)g{|(F}iuXId1>Pe&Iftn1+Uq+d^YfiT<7%45CIG^kF*5u9BqktK;y7vYeS541iovAS9PNizPY z&RpU+bmNcYzBS3kO{SYbWsldT-z2AG8pMtRGyUh!>*W)wOSF$Php0@V5CxG19(vex zs)QO|l>~-d)3m1}nj_LYW65^vBg2ogMLl#QCymXxkV7X!@N}3kX%cco$=hLFY|Z)g z@R(6c$^}uNNsgYCJ-oQZ%O`GVBAqwG->+l%BIPjnF#G^y`quip^=Rv8z|!~!%g?i) z0S}+i6+d*hv}rBy)X-D%`~feVEM(9ES+0Mp@SVe~?GI*=l97;-KtQ*z@`}_O)Qx@p zKg@hWDlCI&v9lfHfotn2h|jmW)3lg12Q)jXmaAJYl2-KA6!?sbtK6+uS{)Y5md*O- zWp+Ylkb+YWhJ}$<3iiM*!s&=*GL+;9JfPH7f9^zQQs+PiytcHalQk?+4ZCPiHuQpw zch8%3v-l0QCWd=H5B<}f zx2ob#9?9Y^w;WnUdo9!0&nxfNJLW&$P+IbNE3U)MCEBQp~!zkAV5szg81ShJvOebf=K zoVZbFn+6k>wDM{n_ncaDzN{ANoNj_NN?Q0prhQ>6K|Z~!u?CVM9@#Ano`*jL_bLUN zis5_BG{GBi7=ynIig-`1GdB=B9NtD0PC?2_#d=r47-Vsxiq)9%nC_hNYX#)&l5Dn~ zi=A(Exrd?$5k8^Vd4tpFtBQ)5lBV;Pi9;Ho5^%;^8#H#PfA0OqXpD^!0* z3bI1#ZK4A22j>Ssw!wQ4ITUZZ2TK%lzyZfj*YDnCz1G~5PylxEg!@Vh^?R|ppn45a z(J2n1z+9;(6h2oE6oGpRyzQdZ(YX}>A$ps0`}_Bx+uKJ8IYBSu6N0}#`T<%_=m>sk zal^Uhb&2?LJs$I~$**{d!xXPd1V8N)OwO5>Vw1BC9g7oQid8_kLi8WN8SvsWZ*=t2 ze)>^K(k;0=@)kldnkY9uNb!*aP@P_NBdThk(*Nw%AK?RvNdh`N((XYn9JwX-R5$g( z!=vN=`@Nx|&-Din??#T3;Y;6_I@;2<9&SRf?L2Jkg#z3>ak=sEWCNseNjH1n*X#jq zuI@h40dk!G${~$Q|Gg~C$^Ne_zAkc{FLj=?t9W?Zvx^If2|ePJCt+u2m-V)Dkk(gy z_HS|AFFDRPzP_H)!ovRk{zCquLLT0Z!jGk-q=X-d2#bga;&KT31iJga4iI$rx&L2< z{O@v9?R{*$ojiS=Jlxs;miyYq!_QZalk;yy|NZ%|cG?Fx{ZCEqKL73(u7kpV?+8B@ zdL;bcW#dF;|6Y}T?i66}`cl=&&EDMySBJcagvb-we+m2_xBjQf{}46(AJNBRBL6A* zA9wyODJ%T92mjHd|AOmZS8;gBlgJAHH}>)*VZ+;A{Esp=Wx&iH@F2KQ0JeINY$ zj7v*$wO-=Q;^9gB(NI+~47jliBW@!*#`f;ViJL2zQfesI-ksCbpfwdRzs*Nm`++*~ zIVYD^a^ZVd4b5cbKC5}+Ic_bD6Yfw16rI`Pvp&-DIrtcY4gzB15K^LuvytqKjUlNE zHaM_@ZzO|9>?Wlm-i>P<*ojFC*eNsKqgab$@$hf6zx{td7{68IqQJkN%x$i~8~6zt zS9IPtu2t7dg8Ll^Icwt<^itHl&2xXz`LULR6;Lddh8P`O`M0%Wtta@_oPmVb z)yIBP$|&uFrg+k8LV{B(S%PcoRQ&3#+p0Wg=6$!W2?<`9dd_vM?C&V4AK+t6*$)<5 zxIDVATc0BHP5pwXuHOOVI-`nqcAE)Dwz4Qv$o*>#Nc_+(&hbRzyP44@>>`|a8mEsl z6uc~0uV=vYrtBYnN!|$WcTLUjfAL+?ztQygIJHt?zKE zTcP_D?Z-YY^R!X$;*HhSEJ&UF%4e5)c|-rY71-Ri8_rg$8V>yc)><%E5^+B6`>hve z#6E7$Ai{YkP#3T(^*}8ST(8#7@50mXI-apLUL>(K)HiYaN|JU80||k59j^-zZ$_v*p$8KY@Yf zk3#}$X(FNrS!^F(Qw?sCym{a~7<&m=IBuy*zOyy%oY!|KxXzz2M#!mBrt)kkMKJgz zV>>=F?xSuJaM*|^Ohe_mu9RBw6)Ft0do*V%Bx%H1JsoXhM=4UopYZr5XZsWf^dlix z)9#{&mcBlV$c;Vb$m?ku-VKxQrPLV`I{f`b^7ZObK=u$PIHRvd-xmLulCc1gIy_W72z&i_L{?d&j>m42L&U@ zRHZr8q+Jv74Otiv}C386#u`)jn?~&YGZDpaPY-riOAQzom&90$mys2Ie|_jZnAwY8MAUt zlod;G<+VMI!{MvxRIcg_R5#!nZw$D}se?;#>zAv{E3WF|us!g&b)*&Fu{X6Qteu1_j~;AZF1F5rIZXW zIL8Cgq=io$Gdm~#{(K-(tIQRq-buT2T@nzFugflyn;|0OSC*V8Vy`J<*+}!=7k-(m z!9FhhQ~H|YdV#oUL!z2#mLS2trSRhkAtzSczya$N=QXG!b=hmfa$VXGm4@T60sA$g z*K7wDA&wD!ToUpmza}1(!Z^YGWn0H<+KT!e{F|IKU6#L@uS@x?aDpq{y(8CbX#BmK zIQA9+`7U)`Q)$Bq_I!>5Uvs`>e|#IqP4D=J`CQYNhXoK*Mn%)J$y|@Hy;Zcqtwb{J z;hgmK+#w$RJ~cZfgRnf{*|n?-FYFg?oh9;k@z%(VYwGDTH%`zhWH{t3}F_4_{zQI&V}65LRG9M_d7@|1)DQTnbx zD~o^kj|QpaAaA+M(z0`Q6rJA*@2@bXTvQ)|sPx zO>S`Dxmaz8XUrRD-ZRv#S|FB6W_>~)t+BVukk10`!B&4S(VHGT2ZI)p0$Pn<^Ti8n zMLMrn!?-Pbt7~SG_iHC>Jr%|KU%{Pz;C~LCy^mC@u4h6C=BQYCSV{!EqDEbA{CRzL zl7(7LBkLT{Q>aYK13{5W`$>fEf}pikjz(zG!R_-Bp_m45x3m@&n_nI8%{U0PS>rS)2@cs3C2UzRqw6M zKisnaF=(`+rIw_1$nenNIj7jJ`;V#f*=@SZrB)wKe@r2Wof7Ee6I-|ukt9x@|RU)t?veQqUU*T=pB zXLaY_TRU_kwq!XtR}Tbj4~>r8n>Ma~`R1x3>O69Axm&BSoVcaCFeW(oJ*_~HmIdIo zD>eNS$IuJbiUm~w>Pl`Pg;vNy9nOMvNDh^zY);3IlW^f?3WeDzDCa5w$({ZgvD;kr zILO}9tp$8EX3rx?AniolXX#NjR1@%p-4$6m(;Tx3?nHMcIcYV`KaMkM(U4Yn$u+;P z0knmFMD(c%_|Fao%xM>z*Jz63xCGit1MIgi6Ej0X0M$m z%^j>FP!n97CHL3NcsEBt6`4s=yF#yeQ{4Cau2srf4|5t(Y@xv_eDBaMH^ata;ipNN z#)-f+*?38B+IPw!Tlpn+@@1$^4Zo(Gtnr2ORax*9EoAG+poKq8p^XoFQRL!<2 z!Y->{+>IPkgq(l<%0#MbN(_XepPjS4YH`87X9F6vBL7$xge3XqA$XR-RmrcJ4P)JV3fe8I&$#inT-?HpO&oBuF2Ygpa@G)!E4J>0Lb3od{mi)CRE@h zJLpwI|CjwEZi+A`QHOq)@W_SF{V4*)Lszf751JoUarTqoX4cxKSek#NgNeyFm{o%y zt?14B)*&skIk1gGh2#p;+Ft=hW`UXl&z*Lr3&SVN&3Su(LWMVOa$+HnON@2z>Qzqe z9K}$EV0g$h>gtU`+l6Ru-_lAkGTq*xbyr}hey;wPU_3KH!bfviFEFg4x=91ozq6|` z1re=o8{M4#<@au1HcJ=kn`UpVW{B6phm8@jId%D(rw&?Z1V&D}j1D39U^}LzFWSo> zdk;4!y9)=O8dF^ztuQ3YVT?xBpLF_fO&fHW9W=mDYoWsGDFf(VXZLpFFK+d;i7WNQ z=DrcGAG?2CU=S(MkNw*6Q&kW*o4!D>>XQG{?4~a9mvL=Xa#3ddk>n{-T+IMM=eJEu z^^2mWBC(xCL$N!75s>txVr)u%sX>Mdx#aRsOtIh`=Vei-2gPWKjr^8XXTWSYau#G* zhQ3;K@01VbIV;dh`DQ!kxqox{+`{q=`@yeL&|0n7e(>Irg+V5fr2WIr@*1#+jC^a5 zB`)^x3Cdy9P#x+qCES5*mO>ouKS7-2n+$wqJDHuhw{Ixb0@-ZXmn&4Q>x`fmfSY%L z>0~VW#-x^R5JV0T)veD?5gxN83W0M05-lhY7N}lk7;_OvYaDv{p+M7b2|Z@+=DoOZ zzu@JV`65)aHR{yZh$Y3oDRAt${SL#%frQKtCOg-bM2 zd5=X#XZd%M$CF`FZ3=%Y@ zCVp+n&pi-{=!%4Cvx__&zU6V7MD?oe@=NrEU3&#QKvC>X0diYlT%(4mR%0gev*w6E zzOIoKrciiw_M@oxq;~a=q4?yb@BGW+hUV(GvNrGDnqNJ6Sc!-#S@!$0$%hsd8%>@v zxV0ZsJTNfaa=$FD5^>g44-)+Qo<(lqUOiUJgz#Ue-P0tUl7Q|aE16%SvPfH_th0k>ehfaUQx&?WJ?o+KV*cLDzKWDut+Jolo@7^~{CIW>fb;wxB9DA%sx= zkiU7BD144LKQOkzX|~I}eG&r`@UoR)I0|r*5!zh)ose{}N1tU6pSP@?$&Ry1V{Li^ zuh9S5EG~wYl|ZC?u?@!H0-XYNCa!6GpPTx04`DM1J~B6Y5wto=ud+7K=4fK&(!QuV zx8AcZBUAn$q`?~HpJMK#amX*(-(Y$l)a7gLTWJ_6wTGH3%M(X>sQ9iVjZ2WhwFCTX zg9l>RN`-M8&UfaLRNAjW_jP6ELHpgcl&khjmDQP;tOAV*<3{XudEMZm)I@&tN3C9@ zJ<2N*BpaM*5saML3$maiq+k$20I~T6VoO6|)kg_O4C8|vq;vxVDK4(JG{KFS5t#wa zIg!HEE6kps%I8jOhgy+tF1NMNh2{zJ^J(RTX6D*pN-ABPI2BB|wb2pEcCdAEt2Xqq z`XE0e=b}0sv;aIhysG&P8De zfd)AarcQ0e9%BZKTPevx(C9o3jUq73;J71Pew z`MdB-2y!O4e8Z?39`5avhrjpIap~8`r14rmJIZE+R{Kv~^i}IwRmdUIA27q&M4Rde z@$)68Ip_dlbhplwtrybZ+A7%fJ`Q@?R-GtE+kZ#^spB8L~-m?=Z;VD#UwG zP*N+Yhl~qjlm{aGU=i(TzflDffra=RSDzU-y22cqN<3<8n$)R$Dx8hVe{D<8REnaV z95#XDm~!;SQlzs+#&}aC+2~f?3#s+lduYj-q{-4V!4hSgKh{axk!g`KzznRu!c;P=NGV!m$K_~ zsI>#|iCU;A&xq6x%EZe@p?<#l{8R<36glbqW1?s{@oxEaGlB_R)L}8VP*_ULxzT*W zxQ~UGsXd=~wDz@I%WkCi&<>Yz@3Jq6w<)=;vN_|%Z>2HExQKsTO;Y}S;ugTf@MnzZ zU@5Z?&v0}!QZp^d(M68Ap3e&SH>g10T&F-O^;Jj8>CvkMrcsjltwNrr{_r&wm1^$! z;aC8hoUQ;3PcUv-GxzFe%(0azt?y=hhrhH*eB#;tBE93B4Z*-#^`_SDf)wHjsj%UA z7HD;STj$&QYL*V=bi#eJ_8RSz3{Nv(w?8z6YaI*TPZm;b)eaJoxHNI78)TkHk5Y$m>@RW?b zL&`rqI+Ka&+r*DJqYfO?HvF}>0UX=@z)0uw4y0n9k}$ySt%<;~@hzVC(#mw=VVynW zF(Hg~+eXO(+#M8|EJ%CIHawH@%4On*)*@_0Wa{(<&F0j`j~Y*kW%CjXFO_Qp zenLj#XK!*^i!04&@cdyk*qQs*Ocp~JGcoE#WDw&yTtuLh1(PRZKY7&aHGc|~92lKb zkSTwS05Knbfed3{6K@aSrRD1aE5iT1dP45e*MC{+8`DE@{9QHAGndPg8A?i`XNiR) z7x<(VV2)Rkkb<3N@g;yiCRpr&J3*PdTKWfTowtp9gQQ4fGKZ0X4*m3mv}b4+9>XWY zH?!--B_^o-@1&;&^pCF{XwR?$hLAk3#GHSyW7P%m8!aK~IhYA>x`JK_{)2B7}S9?MvRb@sx_dg5M zf4*W7DO#@%3A#8X-kO5s%G?cZzTC-rzM52N*0+}CNWw6_{IT(1MXz(V!%?~+DT3_l z73^g>p>dhMz$zTnzA7sDW=HM|;SM1M%WKFdIzHEj&w?a-ouxQ(8Z3Ee=kq3f++PYU z68Qs*+9!d{jl>+!E-~SI`FEMc-(0S5dM%N^#vG&bK%G{J;#$8zTq|rLyQf}(dH&dY zsEJDMPyOF-2y3K1e1Q$munwJLA2ySG3uFxC@GD~glb!ane~?2N0XU|^R-Sd1bM zg|#zfbt1^vkSM?m*tSjf)i)-*Q2&dpuX$P^ttia8LJpDtCS1S zvd8K0fy8qusXF^_8^~`r!wisN3f9ibzRb6*ADaRA?JMt{H4}rRhqwHvk1bWI8Ha z0_N5@>OvEVtzByey@(694Ez1GQzj5tX*zFhAdhIeX7<$|m|GFa5`-su+vD*q&IZP< zFBGA7=5)$4t!&FEuYjwDeP|^jvd4EN8}##7bXJ=+OkgY& zZ1Ky6b)Fk#Mc@&E{v=tRgrbj_v-ye}@Hg7h_Udepy0I`)5>@Ah9xD`ZXK&@RciP~HC^==;Tcnsb+WLj51 z0K`2~r>DLW8nzMLb1C~oj(Nc8%4ncC53%;PfOlfwPP&Z_kp;9LEgv@i%)**E4rL1x zSTi|5T(Y(!Ev1{9QW%=t7KDP)dr1P-Lp(DX&NlXgsj)STb45Cx8u@Cu-+IUYEb+4G zB;|%$dGKeurGRDp=QKY{>D+q}Ze-H^ykUeXYVvoSLFsb>*%s}4UK8u1iarx+Oqrcp z54{AwICa;!*a`6%Tagr?_LDgNfRIHK{ z@r`aLL7m%sRU~W3GTj;2c4_QaB`J>yDAf0Cjbo!=K>+5H*5=IrDJV;lw#aB79svB} zUuQY}y?~InT}MD6l|Qh&X;7%i1u;doArEV8D6O4&G?2b2O}%V7@hOs#Ru=H^2&x6# zi({5&=B8b&)FLuyuh#wTL>34vXjAZW=#v1RH1KaXy2&WZ-(Lj!^LquM%2}TaXcviq zs?q2j|2NC;#}cIu*En)_$W*sQy?V6!cMYkhTp&Z*)+p?r3$~tbg`jI@1(89^y;+(I z?7o|!lEc?tMZ>GtGQ&tqq8){y^RBrez{n4*H{FTfFhhMXw$x4&vQ#&E2D1cdMUnx< zJ^7J;!-nZiyzfIaM;mtbkI}Pdp+uG#hSx@2qrmXn)(g~Rz+AiH= z$_GsrYzz*QD_e%c*42pO&j3w?iTR>CKe>ay%4>5S_S%eM60mW7aP=Sz(AM#W{YAK` z?u3u2eDkweK5su~4{(Hqxw&XcjqVmp70{zhMncLOHim6!jgt(xEA+O+ARU8ae;oDI z+8+i1MdO7M?Sy33+sXa&V)fgG>~}~~w|rOZrGc)!LDs3{Wvqok%K{Uf^kDeQ1*D`U z_lk_sw?Rf%fh}TCY(QD|qNP~OP<$yp;U> zJ@HacQDCkLi#2+rtx?)mNfa4G(v_#Qkf#0C9mgGDUB@0~eMFKIqk`HTOpb#qL)JDbDb?Zw76_Dk;z@0iG!jsGzAxVZ+Lm6u@jg&gylC zC}`e~>|BuHP0_sg4M&gilb;)VhKEb|)zWYbjI@lh)W8;jI24sED1nZ-6qPwY^q|f{v_& z$HZQDqhbKX6Mw0Qg2E1`M$zSQFrmAjELLLArf213LUq&?{hpzNzk)+81!|q`jop%l zJf7|c82<3p<02N?6q~&~r|?!$XMA}6C%ivVLMQWqiRf;Or2TmER-?6w(tI{vqNNn} z>r$G8o}3Wbw%jU`+|;VowZ(Uj`h}amX>tyXC1rz8 zDh$i7z6HY=GlN@UNr31>^EL;hw9`aY9p;6ZpPm3UPnraJ0vfX+u($TcvtDbXSf!}; z3IIc|cgUh5zWy{~@uQ#~{+Zsy(>J?MgN*tc+7T7?^LTz3JAssbdO$E$rVigZob4oa zX7^mpvPBxsk6f7npF_ZUW|Gh->C=9 zkekwt+m#cq3^?_Tta48yd}S?y$YnaP^1vL0h;uCzqssU0wVMP%+uVNjHLb$XaDRxe zc3n}-qBEE=JzLtXsNH0Q9UR)OhuRw{1EL8z!DNh86R0ejuksXKvE4Q`};?Ad*-a6JB`r{FU;eBwF>WX+Zyz z;A$-_Hs@K)c7~^a5F{<9H?mIQaf(G`s~UrBNhcFKK>8T^mPhA4D#6MJ%4%8oDlE!n z=2MBl(R}c6%>KNe>*rLYa_Hc3;Gu3_)r||uXVK(mU|^o3WU1->Bb4sQ+5SK77PT0_ zQ8A!D78mGR``8qL39@aHZk(FX7t{Nt;NIgN_a|S-fqk4Qr_W!-$~TfXzO%n zx2frke>cE;{0mTswGO9n4)=^gTp}KqoiL$*aLB-Q^>3$JqjiA?gl^^!C{s z%I5@Ox};_6Cet_1vOQBpfpwzrz?tWUbsSo*Q|%b-ln(l=_r@;H9z_qWj=ET7+WZ>c zjaNCmcAR;Df`74SJ_G<5ill24bLMZ2@^8*X`ZMq?hW~q-S3H^jzl>UPW|^vVFoCB9rmq z22X)myRW-PnqgpQ2b0jDp8c+0NOK7M!3f-`p`GZM2u98-#pmybnPd@Zf&$%3W{`JY z&bDAn$oizR7>$N_VLSBx#wzgkAG&0Wp_gWUlB(qd?dZVKl_ssJM5-STV2!KA3U;GI zZ1!0#AV$WE%?|_K?WHAK9%i@p^Fpm#VT>1spkhC` zpLn(XhHHzK9kC9Ds{=!6Qd!7ga5 zc}}!L2tr8NLfUn#vYAb%yk73q>X!zPBOcV;WfjQU7%t^3U9u(PkQv6bIpubqmy3?z zwzN1aPZ?-8OP7Ep^1Ldy%Z3R*M`pe9`tI>&v_qra;{YSN`bQyh4cbXQFkQKz{7#>d zi&@_F%iqUUzwNha$4Kb~i5KZ6=lZoj%=c+`vP`y3@q{;GFkfx&*i} zzVdeeEml9_FqAk$NYSJORU4`wG(uJH?j=pqI{;5>w6n#g7`Kvp?niXe-7~&CO$t0n zJfkqFcWP*v<9QRzG0fz9hdyeOq)^;h4Nec1Z&{-m##h)w)}RK=Z4osKVzZe2>@AKB z>vm({7-ePSYZW5(GjIFd+QVhA@xs;w9xPdd3i~5=qIiO2r>;~dyvJvF<5wZ~ue$Zz zppesVO8Sl3r4Neplo}iL{1ZGnE=SzULp+{hfIfuVhI16tZp)#;(2e25L7~s5huXzu)tArjZ+!E%PSG6i^bq!kK_2nyz^vi=YlX2z;rP=!)&koK7d}2aO*%V~ z6nqe{y}MGmUN(`Zu+WfS*Wcmt$dX`t{wTEFBWESMsJ5ze>uB+q&53m!*?Dr73w&Kv zfkMRwUbQ%`{*V@5^mAM~+7c}qaAuN>s?LSHx{3^&7?HvJ`DeHC>0fT;Qn^e;I#Rul zKY?D9vUH;y`(1YYLZ!_ZI|ew~d@NH4KwME_@v4ESc1)`I($krwphF_geA1oE#*J^2 zTTBdM7on;wO_^U-{#f7QEYJ8dr%3aJbf)dKJWJhAZF+FOsHN{mKppJ+ z%6D7UhEF_@LR$`H3r-UQVLmgv^@Bgw+tw;_D0QhpX|m_L;fLm zemd#Ojb9$C`6)8H&dA!p#kDeSpMG|O*ON|WO3w+Lbq|Rc6vQ{syYCwSb-KW|(`ENwHnBA=# z_c>gARN3kL$~R1XBb~8c<`8At@>tEGSYQAm`E7@Syivp;uKJNdyvqcCbeE3N@RuS3 zPsfpXo&o9+J?=-t_hJO3TA z0vM^}cw}wCy2OEW*?cQn8J`N;S@~W^ZXfNKO-)K6(u*2%&Zp?M6a+bGD~Mjo{to+& z2sd)rM)Qv7U0PL*P8}FyWPXCpYIiyz`p5ClzxafSmz$)Ffaf)ev>Cuv4^X%V)@y_> zee-n{%=_QpI$UiTG1j)Q=kGhicD-kX`X@*?l&MKg|4Fb_E#?Je652Q$c3QhOw9pof zZ%HEh5AK$$jNpQ%P7O85d2E5<8$*vx=77Efs2r%8F{BQ>VQt0w zXx7+xVu~D@o5&Nh4axF5Uuq@GY~86-NVoYJ`l3t4ECbayc0X}Wdn%hbD`H5(eg2`; zQ2qK+l^2vPxX>6JvA0%j+R|qkJE-i6pP-9p6jy%Z8JP%fT*Ce=oyWE2^=_d$?@KOH zo-M3bzCTy*Y8`K}HAg@Hcg)Id<}|_cQ<~;+d(dX1m*Vl4t;7dT6OXo|w`jWL6&Q8h=PxwoY~C%*`?h+40gFyo zigvym1%%FdI@oZ2vID7M>;Agx(jW%Qw`bx$*2Un?>YzKI2ah=RvV7bhx4V4%vtd1* zMH!s%4dnkPf)>@WLmue%N&)@NOsP&kC3CMeVnqB7Q`MPD*_8|Wiq53DuI&!%B-GfE zOgabQwE5d)756xRkgSm6pF%**cDP+H=kCDv8S4}lB2MLp9XgMz)?4@?Lz}0r(JMBh zzio&(6>{Wss@hMs9~6I`aNaqZpBG!rn}Bntty8EHeqaW>Oi?Bf5`)*PEs8I(M(iRM z&qt-2>Ub<(w7IReoR=%g&!V;F+IW}QX8Z;gy;xARWL=ig>)?ZypMo=eC5>xcq0#<~ z&SZL3EXD$!yKlD?`c}I;=iIKg1|c!#_YXVf?3>!%-kF-EjAkg$nu~iymPWsXX|wFs zr|^hnj?pkqU1b(g7aEIAp1dPYnJV`Tx16T;NY^hnG~T460`$EpaK=IEHV~=3Q88h! zci~+JIb;`w1yAYEwCvPasz)gnG;Qb0S4+Ev%unVm)z0SV`L47fNLlDDJ!M)~0*a$% zymqv?)f~-Go|u&FM`~i~rO57{rhzX1)rLWMTG+bG3H)bN@OXRZV<*G?XQ*|%c4i^U zQu<1zS|O;cU`zGj-8bKy4(ZG}bjvr^#FUzGiu#OrX?L-~Jm--?QBd)CDCpoxKghNt z-q!hUgP?iS0K6T;t&=(F?NRvYMG?>RZ!=6ROu6WQEOT#~>F3xXg`|-`)`W0yH;%Jx z{~0~`M5n?g;(oo{*w@l}_v3UN%4F;*)z7;vXWk|d3e?$sWPI;WWcii!bEg@PWo}Hx zRg=vez6My@FI(J(CMu*>hqtLUFT%kky%Y0v#+Px4!eO{ZMU1@&J?3P_{UWY-*m_Q1 zpukyN$<1w{z8-a7t=$cAsU+=D*guvZq1nH{`3?^7d}y_dsc`!8X9RMe#bG#`_5^~= z)&)m0L5$exhjNkfGw`ywtL=o5j+#J^V>===X0gN4C9qz@?v=zF5b9|6DtL)PwaTpH z(EuvJXQ*;P+pjBP7+I#UyOm2K+q$xO<3dRuXM`Q-;T${s_RadaF16?c4Fk@yq;1g> z=+}uhBkcx{<4+%66GXRKf)H#XDazpWcEDwO)$_*(f&bnCGt0nux(7ai?5Pw5**C?8 zt!%3P<2DzgFj6wrD+)Y3EVi9e?-L%LBHrJ3-;glkY@Ic>-u+y#^7O;P+NUM;lwVy_ zIJN4(P-`UD(vI`w6>t{X32GT?rtT(dCO*`FaAV-l`mR8sP`?pb^iYeaZS++H^bqTh zGR^VXlS29Ifp^3aXL3%l={#X{rrxT%B%=9;krZsH;gRJ1+sB;?@WRjZcU=9vhmC_; z>zGA)v$Io$+{`ktuDPqOj2>B4dcJ9MKI`*qqQxLCDWBD-8Q$jKp92pISMv2{yTNR3 zyiF2iDF476r2lG+WaRu=ke^2)FB@vL+J~2%`N@N0CW!>Mg~mY!$83%|NA2W04C4?> zedN({ip*+GhxP0V6fBrD1Y9b*30)fiB-tUtR2reldozQ9fzaq}Y=7Oze_yAq}Cwj1;{pZ!xA%=;T@+7&-#o$4^UB`0d ziJrKSK$8(4vyXLdXp<>xsOYlE$~gYPz~x?BN+-ywI zT1yIZ6PTOYX+)*Y!yM+fw1oQjP`*|CI+&pp)bxc@8t}-DjL-NH1nhn}pLVdOx4=0e znUYMjV_{bei{ud=N?CKczW{hVvpteOv)v9g(SrJ?%~iP#HCDPm( zJM+=iRHW}X4SYXE6D+tUJR~4h>kw_mCb80?5Ybrv&?KdgXbVq8$O6^Lo{S|3UTwk+h}ur8;H%qU|wbgxBc+>*dUC~ga==K81D$(3b5Sq z&Ej@x!rG?kiRXU)fS>z$U*gFJx)6wK3vTC$+SOHXvFm)>(^R2L-43hfJ_VJ_jI;F} z;M&*Enx})Ye#=dW=>a*k{3~mhMK??A8!G6wcE3+A(nkj7q8k-!1p1qe)~a&4rjiKtO~z9JY*9aJ3@j2T;08#b%o zcUapw%RNO2`dcRar0)y1MI2ym@m^i*2)A??6M*(5N#&1=c|o!|IY@>xe`vS8X8)hO zYRt}09`Y=dsEN@hOqHz7sUn|InVsRxN{jmo8O`PBD;d9)qTyPHm_W8FQ(oL2yCgCu ziI3<&6mtF3;NU=($I+pK{m%lv@tu~m-HXDs%*B3I-3evgC=(r&}8fFh%c`V zKy`W!I;pO6wdaSgX;9HDywyjbuBtM_ef}*(wf{@W)PH=prnvGug@DAIkFfrOxB|Vj z>5Hm|m6s{jjKZE=PRgKL=@E){7r{IYxTn9{69!f7>)WTip1vQMda|E{M$i-&P+2p3D6r}KIjv)zc^<6vLhRkr)}Lf zW=)q}@(SNZr|fQua~d``y4uBR7g0tW90aJzWfjThhg$F;{!~q=`aN3|? z$_RR)_ldEm;6w6 z+W?!W%ZDgXztI|K{2|W>m>kWYanNQFZt-3_azM6XMJQW*W`qLkCz5K97Sx+(72@-0 zTD;fe%^Iqb%(oE_H*&2XG@mD@Bie)GLS+3~wX>fX8CO`O6!=KL2bhcOrqYonf@tFL@5J2u@H4cLzNUFi(zpWFPx(J%{(2~D1B z8-X>2sYLb=kBC~a9iaaCRg1R0@41pY7H4g2b)T+ZK`=4BoPe-?V0*OcG+I_rn+fn> zyBL|wXXG*Drk|NJiVf{Hikkr7$_|T6>IH4t`@Dq+^G2(o`){gu6o;g+aWZQNX!aTh z_KivA6{lBUu4RiP5P+Cmc8V}p#-TLqtM;Z6p;_zClTd5DU7zTpfWwVX_C9Y9ji#TX z!Ya+1h%oVc*o~l7#gyoG>Rh0DCHtRm`1dC0ZmsJ?|?63~p?$I7%B zWy=iwIw=W!+NpUFar2&+S7jN(f|Uf#6%LGCS%pJBTCHCnwh#Kmt9d zV@oVAS9>0Uabxd4JVqO*0TpuNXVuEHwgXH(j0H@R+C`3&Qpy2Z-%4<^4&aw{>eY&3 zE(a2=^R3bgAqS_xg(Al{W&UA497!S7LgsBov+~mqWkg(>My=nIU59TvMKNCqKkWqi z=%i@+pVrDduMTP&R~<@IkY(W+hhF4{M3=jrX_bUuM6L`b&kdCtartc2K*gLjRu-w6 z7G{-Y6%J|$!L@v@XvAQ3(Pj+E!euW4yr+00bL!A@{Nzt$l8Y&*^6bN7qw3FKqAj}u zB$D3la#GLfOw^g$=vRK6J&UAm^fXZ2?{7Z`nl}dbfPIH#NF6@MV$~2#;=ihC__QfZ zoX_RCs7Pfl*l!gE#g z7FEXt76t8iX2Bc20oXUUMMMx6nN~{9OM*V94ryIGS($*MF6E*#;fTV=1p~4bHPQ{< zA%?a4K*L&5z+CMi=yVOuesDZIx7yFy)R&4pc?wZTP0VRsUa3a+e&b=9dvYw0&98uc z%YJJP9HUtUCV|c--8jpH`xW}J)s37WM~tj4MvOpyvAO=LZ^3~+=`hx2!Y3P-!?V!V zN^=PKJCx*mm~E4`DT@oWC2~UY8WkJ^k9hgATSi{o zlhk0TkcXi+>J{PNQY3Zblviq4kbQy-JjRdvnRgh-%7W8TL&?uAPlSBS-^GxYx3(iR6oDTx;KHj~H0ER6B(f5fG42hJ&3Pc}f`LdK zH%r1c+B4AtjObrH=pS~{=z7h9Kefy8ik%I!QwH4+aF};WzOAU`dMHv8*m|+DT$+En3Tqcf{uv%{+qz^J7JX&qZoGkX+ zO!9Z$l;^7{DW0X{kiW+$*iE{mYs6)cuspj3$6KdkuEiO1On9`VimTHix865Bxb-;) zH{-`b7`5L#@7r#Cb=$`el}y)!0D(Owl*^1NS9dkn1~Tu?)brxk-yv;!zSPdUl>-QT z0TM3D*j0SM;z?<;*k4=`;l0^1$-7(OdFW5?$;gw(=eH&7N6HOO#$GYZzmYro=$}pK ze9)VC2eH6cOakS6n|D|C3%t?VdPJBy=$=V_CQ<^xHHNk3d%N1wJlC0tY4Xf7YM0vM z7!Nm>MA}9l`25vNRjk}`QGkOt@@l2^;yt)iIHT4}^Y?Ox5zgm99UwV|Z+A>r#}#ms z<>;PWoy>EK7IYuzR{986Em=I=3UG3R<-(DmOy~Hk(#yzki=P4QOaz1knA66;xO%Pp zMh<&0LDk1Q|Bzuf?H%ozmK5G0t5F&lV%C?^DnB|nuPL;UyTuK0?Z$r|CNfhSmGG-2 zmq~_mt#&b5qukL9VY?F}ci?2)PMKFgk=J8#0U^>GQ~lTf+|E?CHOPwT4}OgYOu3(T zg9|1pnX{G)j!#W9Z>woP_#lm;E}r)|y3u<6<#W{RvnVeUNcs-vTfn>5j32Vk27@;b zrnu*DRa>1q`g7Qb?^!vXV3oJ*Im=)0>>N4igmI~60$gNw{xqn*&rqlD48=^YnyZ(- zzkZj2WKwFsLvw5!;ZSGO4VF_{SuQVD>8;=On~t)GtNspua<`sBEg1EXJjxNwJ7|V* z?S<%R;{uvTjM64V9Skgt4Lc4440{ddv`Xq$Xi7fY`&bYikW68%r*BYhw@Om}(R-aI zGW{d96E~hF*i*h}FEAvKV&wai>exy@eccqH4D+KNk ztHTzX^~w~PPIu5&ysLQ5lcc@xTOp@&SC3IYovpf)XDzHC-@2*!&Qg%$J*+8uVu4Rm zmvDK`d4OAlp5q3@hZ93jZINk+L*G~maJZgf(0hoMXUfGnR&jLM3|_32COn$|emz`D zPZknqv@o9kLh0N-9x0OZW48(J|A%dku+fI4(n`@`$4NIarjcH1G`^K>^MB%u12o5n0sSq7+7Am zA-sLf@N=vof8fuLQ#Bc@DLIB74mX8;Ob$he9t6P_Wz-ReRZ8whJ1h*V74>y+eI zJZcq#8Q(;mOsov0Uea&t`Gu)%pufABO8TuG8LFRI9QPrI#U;R~K8w zcJG8w2233#+@P*%H8z0o;N}-_kyYbYz{^xOE^$R6ph+S;d9=aNJk_E=^DEF?S^0&s zeUDXQwgB|L8M^_U%d|z|%HU(v?x-!-UgMHVfVseF^( zUG`>{6pk5Pdsdpd$}dKr@s846L1$whQP|Pe>UJ|(mj+dS{;?a@$f`N!Wl(Vfr;upe zQ5ps*Ai8OMboazBf^w#t*ZO47p_B`Pa-BAoYXbILU{sC>@Cq8Q963}Vq!P9El!-e+Im__q-7j74X~ z-rc7^5xJr4SSf{Y&qwP;*ENx#!%~SoaWptfNuBBT%OesPsNG1tE)UvKHBOFehuHuZ zsR&j;iKf?qE38P60pI*cnMIt~RHH0)OAO}o=h|8lsI29Q1D(!MfJ|E$qalmf1<*$@ zdW*~^vIkF2_v(ZSGmfERlR}q`@o@Ho88RpRL6tWe>q?t|c?-%bSssGDlf?(k<#-ny zq7>~grHM-AmnR)q2jsYzC{jFPk4@1D0sIuGRqeJUMp!l){S*P? zF)}Ah`=+mUDnzQz?IxdwA@V3ILW1%NEkk@?s!+Lo-%Z&2((ctp*tlannKmMIUi5tv zzW1O)72D{1`aa?jg)y<@$g$fBZuVNWv>M>8wP&BLsjfc>9!nO&}!GEDFP)#VN(e*2hmSy#x&L!tH(nWP3!7fNK zH>7geBcQ(p0*(I&HtsjAu3r9Dg?9(LLj091AjP*S{p2`@A-*^U zDFxS~)`P9TAN!}oL`Ys|D|ay-uf>L2n~-0FhMerwP8uUT7Hq~44tw<>3VuQR^9$Ao zQ6A>AUNx-P5sTSop$ZAT-|#+H~no*8nf)nskU0~FI1-;9y~Q6AG6!lv7=^aXg9@ozohpl1&^%Y(aI@tUnC7Rq?& zYnK1%x~jsSX^u)_87n2b0iO`yQz@iqLLo3BzWf7}51-Kg_ zmGQ%G&^qly5c*_0T)Lkn!#0*5LDM~8#XF27r{=b`UEFx>`J z9-VFaqUVI6e8#U@UhOoHEjLgW(blrNABInF(Q#I7WA;p+RNZ6Z08Cu5T-dAM5$?;% zubP__*QPzCF~kZdw2sS3CTHOJSE*LYs&FRy^n8F$+2 zV|Kg9P9;W4g&w$Dmd-seYsGW6UjD@(3}*Te>THrujzch0tGROG+Q;;lzJMiFQ3b&} zkleWGO@D>G7RxP@*HtI)Mj*kPs8uoBAi!jN$7NQ96rF(h3UWoF~Aj&tU`l z8$h>d-?ta8B+0W!mw7G%uVcdAZotRz?&2MW9?kU*NzEej_N54N9KJNgL{6HL&MyRS zczD<*!u*nq6p?DW;Wfmc*K3!c^bOLanzlt>0vs=MWUP97uI)Z~z|maoAnpm7I2`jt zCIc$xPWxpWLX!;L_{|YhIuI zvf$hCJ~e>)tSzV?5OL3i-SNj>>t3Sm6P`QnO?kAwmPi|h0BFusS-Sb-Nsm38VZiAN zx^A}d{e`{8``*>f5$Q$fZIpMR9U$&VQT*r}0x_Iym<${A*f2?WhH~2zT_Q$NHI7iO zi$&@VuAPYlrNlPJTM&;$A;RN5M0I7(RIG5$tX5&n@kLMo_m7ODuT%;}TksUT@O{RY z6YMRK0Gh-E7D=@RTicpl3_=~;ateqD^ta+{LmPZ;Aq7c4!qP&*>S0BM2G|GAsRjeD zWH~G&O^fSKgm1=hA-L~|#n*2v_b{s(m-0$jz-E0RR!=Ub#F$3Zs~N z2a0dw!)5P6fDG@C%!#FDJ<@{y(=#=q6E9~3S9lrPCZ;ZA#UDVT#QbG<9!I6nggg-# zO_9evV8I0**MPsLk_uv6$RQV9)VJBGgJ{z)3aK-h*qy8Fss<0&Sb3-TvTSNNrBODm zyS5D1*@%}|tv$NZK{iznK<7>q2kV(ucceiO;6z&Dp0n!z6T z=tveBHKHs9)3+o!wi;D}e{hYDVBczKD%u*lulDA{l@9>Jin*{xPTGNYcXBr9w>$Fd z;e91Bn~mvS#b~|^YdahM>05&IF#Ll4=46S$^0uRfHv#|-@fb@G3k*Jz^tlFQeKa}p zApjFx-G(!j6mN4s3dcy^v16~Ack8&*4QZBZJ0*2;N~v{JvSHL-zyVFU49XQ7*>B;* zA1AogE6cngB#bO46VB6Zwz9e;)bkHuRSyN%WnHjF2Q0d z7V+{o>ZZ_i0A(5u&*&RL#YkAs7Fi;(>VkoX=`=+jqBJal&}IdOMe3eaPL_lEOqA3W z-TwF8S4LP)nNF+}cw|F2V%kw*7|bW(i#nDpj48!LEd5Qa5;6vE9LDSAM`(y1>^}Z3 z(A1pL)ld)Eb_)$rjd(eUilrl}RV?;hqf_{b)lz-J(1qlY@l}h>ipsxVd3mA{+xS;x zI`O)-uP`U~2&uZE8f2u9zxc027V7iy*M# z!)q3H*pv%%(E)j7NvZL1Lo`iD=+dXhL1!62v5+Clx$clh&`1pgPU6M3F&TOv)Ktp( zO4_e6T-_b795Sl(>ASf~{*$J!Ip~NL3(qd9*Z8Ax5ubp=DIoK?WzjzA0cN_XAeFse zTXWux_1=^K)SN;;3(z#NKTo=@P6!1dg5O9;8w(@CeFzzi2%D^X5jE?L07Y4e zz^ro%HJY?4TxVs#{5NcAFx+h=dcF0$v{DJl={)xrlgQ~5hzS7wE7q|c*B*O;|FG(O zsBX+6_65KEOp}OD19#8V=Djg~-;Pf(L+KCq)(gzHoZf_BH=bR;2EFgS5So39p`)fM z90)Qx`1}DQ+Yqo#F8hN~1>#`JCH7Hdx6}r$C32r9NIMa7xF&S6=nNzUSYhEy&2Ia3 zk5MI;kn!`4LFu#8NK?<&O>xI8E=Lhh01-|h!q{N!uz2LJ3pD>E$`|$I)PydWXVm#Y zA6$AAyI=5#Sz=|Hefm?L#P{l?S>0!5j;G4wtt+S!9z{Fc~8Kfpqf45qC(g1>r|$;>i3u2jH7@ldKk2_aPpH>;m3JzrBrM_ar@i>=s(lg57Wzm`m4%s$}}JM_c&Oz+|`e{l*6 z=0|?Z=vC!b?ye|{O}*B4;;3LcX;cXL935X#U@V1Ti%{*Iw}^Ig55rh%e~W)zHjN@h z(Z_quf%tW#rFvb4W@emZ)8`LpoE1ZhU%6;-zZJ-eNy^^a)Jv>lY@O2Z;XV_Czh73& zb&>noT0;`3>}~oT^Y7yx@P5W5%wQp^h=P<`DZS}wOM=-J_H%21R{E8EfS{H8^A@17 zAu>6`>l(D>B4bo*6?N+7Hzwt&w5oH<6Ne;UH57MmHaY!E&e;Ja!#7ZlpI@W(tm=p0 zo12FlCT}dfFF(f+W5HIVIpfrA4y$!ZqhK?rrO#-Pj9Tn1^qnchR(eaj*&EvfXVgd6 z_-6=RY{q-L;ec=1C6@mO4>^or>;|1qV{zwAxvR z=hd?FjUhsPnZ7K?8}Js`qQuKWMtj6?0dMuxD`u4wxjb$LaEc@Loy0xBlu`J^`+g#$ zcwl&u^J2?pRy_iIf}OJ%Qc?;Ry-ZNLd?!Wc|C;jN)}=7AtzrRxQO$Jr_?Fdso1SGN zNtcKj?FQo>S9de$Dcly3C}rgGP0w4`(oT7Xb!u+1s^-v(Bjbo}xiMVU=Wm z#lF8fM#XMc}&CEA{&HJO8?!y&{e{KRS#}m{OgLe~wPyPL&G~HmmhX zc_6yj*=C&+B0xOiz^cCis*ivs<=LrHs*O%EJg**@)jbe+SsKQ=II1Drm~fk9er_m) zL;lEvMa=Jov>SF)&q?ns<<%`s8hb!_5V3!S8>ulKm9x_Lt_A&kSzLhw&jD<3wwY;l zs(x_c7)M0Vz1yeH&0wx)A9Ylx0wi0Nw(!-FO+F?-K2oZiiI8pdxoULCTr_Enbo!kn zNr`o-u*EbnV~S%s7=X~ohgnxKT@vBF1`U3&D=W`;h&-EBdVr{QThLdna~KprUbKu= zygCmZhhUIy&+|XMYXM(Ieo6n}Nxd+vfoBr{T~Z$U3Pn|ZIUOwE{oY7TrRG|iQLp$g zuUp~kF`e*8;!2ej;RjB6e;ytoYFXCrckA@x^dKYeJl0|Pb7#1h85*{FZnxN|I=wCb zYe0ibmzWl1cRrITW>n?aJ$kW0pA-itJKok-!`f8&v*P z!A-;Nlbc9ZpZ1flm0E*TNjLm`hDGiZFD6I&=GtwFsa7)NL=GMC>r3<&}J-;h(v{Ff>=mzO6Wle+U z>v~#=Dwo=b(Wp80rVsg#CQdM_qYPTWwG>*U*IY2|N2gV3ipicP1RLfzQXS=5I#&c? zyT*pbUM~%e_iHUgpe2*>U2~S@>&+-BH*y8xCQVS=n`~0>v>vlwU|9)lEn{%=&kRd= zP}&6cPZj~oG-vBwE5k6+`#P$=!3jY+QLg5@V(uE)07WZaM0eOaB;{N?@n~5&(Wn|_ z%+9AC{T(A_Gb*U#EHTZL;hI-TK9I0=d*|Dr3E~m*$PHpVp^(3AS;#ynItU-|8U&8p z1^KLe4P+EW9AoOq9@1sDvnEY25mT4r&mo}G&qz?)?&n;%`L|DvDR=cwKK7LWmEd3u z?p5HVJOtmy>~@aLS_<(@Whs-LmKd4#?m>&8jb3S2z(pqw=FlPx5S@foS%il`^_J69 z+ueBE=2aTQ=<&*n4UfX^xz$Qf`>8P6y7?{d%yX5IRF?_EF00P)_TP!YbgDN)Fk& z*QWaPO*k3^DYynbQ&CDU%VyVMRPuajP3TnRlPH>mYjuARc-aANL52{yBh35~^55$f zfQh|^CFfy_9Eu|`5AmeE=^8NNv2Vp?tk5LyE_+9ELO|WsM&cXB@9l4V3qKyOQEbs( zB#5-{SG*Gmc;d`l`C+F0n_V1`e_>e5@xzYKs&GP6-aA^gEvKw-Kny9x0y8>fjYws~ zFE61~BJV>M=Fv2|)uzqnvze}KaSPiztcwEXa0819VpZ3;-Bj5d;D}*bvyN){LMyRd ziy}fG!)Co|F4P@EzA$)xrxx(@sH3^KzRTIeJC%0)>m1`AF~?xEJdPkNIH}Sl^XX9F zS956Z2hCL;7l$Kc9}aiXsQskxRDh6=Ta@PHFqd2Neo+msla`b#!_2-Q7$n+4QWS73 zjhmlWUU6r5-RBfjN$b`EV)vP?G)f!MAK@GX3E~ycfR_@+9EdeqadxJ@%tq%Zc}dr2 zZCA2lHX2B*1jQ%nbh}+;uVdfCl={g*Ro~0on#15<-|rQIqc`%o5Q=;ILmjShd*59} zw|C#71G73qro2)Cnd2q-&nhLD*+^tCPlulWZ;UL{s}${c^zkv}nj$LeP4Lu6CNs%+ z{`1&$oABgWOeS3AEYqz>r(D5xvfEUr{8=#LiQfk=MCvmS+;JX1mG+aT9_H|BY?w(j zxMlQ(xtoF{3RH@Ey{*9HZf?APibK|;KWc7_gRBw_oD@t2(Byz3YSCB7wJJU$WHWq-~E*@SjJ&u^^M9rF{ z9xy+p>#WG{`O6p3SCfG}8^S0anU&XJ0#}>;K@t(JN}K*t=lI@qOA<|O2mw@)*n}zX9pkD-={+h^17gelg5L_ zokm>OG<-xfOF0d9ukAl@K20`fS8MSlR9K(J!?lHVpNg3pu zV_tBz@iohhYU+@Ukvl<71CIb1YVtcy{zbTHlDYAZTnWrwqk3`|Lpxn%Xuk>I}?5+qx`8Az= zm#1xRCF_KhZwc|VX_m`dnU_KQ()63*xN)0FtSG91f5Pv>5>AImK2l1j$4>jnRq9va zf+yVsyKgfoegsus1lsM!T;c{^kW|$>MhGM*omMPFU;Z^jEKp9^Y<;{BN1PI)bNDGF znxZR=%TR~+xTa*%1ncf&(YE|4D(v{s{^CWin9s_s#m?}VRx~UeBWk44ZH2V z)=nWOU1>iJ_a%o}HW#qVhG5dDb`))+Nes7IqB%B3qg|&9*QpLBpL>3Vj7OMk?r)F} z$iPKW`EFYG=waK(^;Wp!g#+xa{*23b2?Jcn=29?Zv$Iib%WBa46cy7g8?b=ZQz8iP z3_8JZGZp=9CD;Txu&4dy0{ZX1L=MW~Uu_o3FNu9+_}J#RIq}`npRgkw=7rUP=fJ&C$--SMDRlmC8_|!=u7|p(HoKq`$szH{V~N0& ziL%(UOxEi^fp6zY4Vt^TIXv~wklq*1?OSrBXz-g4w`%&p<6i4t3|tc@MB3U)Zf5PZ zNGhElSRez*gnz}IC#`?d#Zm6e1n5fyvI2x8-0cwjQ{Z!T3BS{X<}Om7oI9*B19{@| zSJ)a8zNEVR@R{+9=)r`=u6*{b)2e+w!w?p69S1|Hc}~}M1Cr$fH)?3gQYBFBAt{$PAJfq&`l}J-+*Y+g2y zWbF(uQS)7-^9O)?^9VckhR%OG9&bt3Ibnglxe8gQX1O3Sr=fQh_)V|o+tMDXyK@2Q zl)h#=?S6UuzH>xU*Xd<#XW(99g`@LA=-T<~@KPD8Ohld(xIvZDX(-!_66Dohd6N1r zubY2X1Lct=?E$TvYs|1-0rtAZNT9b1QJtk-sRp>ra2%%1q1=6;Wl(ITKcJCi=!bi6 zs?hes+Kmtp7B6Jc*o!3Wr4&4&oO8?L%cuLAXfmRdK5LJ`5gC(`stKHb5>LIt5l>U! zou9HF)KLh_dM&+o7sVYD69ErvJ=JflU$u0#VB4u9Zrg~eJe1p11svDZP6zqpoME)8 z5;#Z4n!q7rs%d%a{JgIHa>%N6U<8xpvD*8 z1m*szyhIRr-=V`EZ~yJk^~bMeNd)lC;0$jLh;*OQmOf)27d zh!d!nu>F8IjleZ;llwhdQmNeC>RtSz8cYtes)t ze{c6@xS4ro zi#UjCuCR4;@1kGDw|{un{~zE#>$NNYe+&Ne#9Sfye_)AT7AmjUm?6Sr6<&;WQguDL z`MVpy6_Q>C;tn7$-Kg@b>a>5~U?YXOmZp?n&Or^u70c zzMbv!Gi)_$^-=t?$l~7~>UBmD7}--0eW20e=fdkT+mOVk!+Hq%qEd=7XEnS!HWBf9 zv8@vv-J?q6vXmXmxv&46qs5oJ|MsMR-`@V)S3Y?YTNudG%1b@@-8oX_0&iP2!`SZ#qKg#H(yo|84`mZkn{^whLg59TQe5oDb*R%7ET8-l&k&W%xvopEv zpB`AG0kb9DNuMv}<9CYwhu!mkKI*@Ig#iBqx%l0U+r%fN&n{*!)5mwdqn=P>Z$SxoW!Lf@*-)_>1Ioe#gc;0+B zhuC&S$L%ZB#c#yj!&}vfoMJ3pqL?Z4HJV!sQsX{8@S6GMe2ZP_&TPHj!ODQZ>4AMh z6ZYQ(%eqrfmqGByo|;H` zE;`_}QhNRnN%(II;J;4SKmWlilmrOTSkQ`Wn^_qU7gHBdD|x8u$T_ImMauIH2^gS+ z&Q1z)z#@Bi)FtSH)Mzu8>zeTGTK?Dt5f<^HWM8Tk+l`$cRS$kCh5ip-c$d=omJe!8 z$(|6Y>f@OD+Q)y-Jqbgdl`}-0mc#cGb(S~3V-P#27`Tzh_Q*@W@$xbu%*Lt|<>WM+ z`b5l0+Y>k~s0DL#{^w!+=XIkTdR1ul2lg_m&KC`o({4N=HpM#iaY`W;b84OWZQiZ? zY1^!+#Yg$CZMhk_A)F=hMJ{}FEJTj}Mh$T(jlAHdBcA54lH|TURqMaoID=lJN_p+| z=3TUznf5KQD0_`O3~gHF1u} ziha+bIcJpk+MXXS_-jD?ADmr7|I^LCB~`x4FB#d2V@8AEsPz*UOS zH_B*XVM+8aC&23EYMBS`h}MP?370orNTB3&?C(_hs9|?{RUHu}+;nac=Y$^r7V(-DG^(FA)#>?ws_B+htdk^_i2V;_QAQ#gh`fGz=N{c(In-=fsjy zGH!fQB85q;QM1}L=63@7w5j6+ZJvZD3r80X8 zVK-d_9?!Z$pfCbHlE3%Ee`FhxeE*twIXWXrY+429hEv+J zia%&%cr7vBGH{7?cH-CC#PYjy_Yxg_n&ye?gR#m#TuOOz8cJED<`g%1e%t&tB#p8~ zy2Z8EoU)XQ;*>I@&+>G$7#p7#?Iuk~6oDO7-gX<6JRFm&i)(`2r*$zek}XP&J_^{- z+X!a;-JzY35FPi=9pAfGTqsp%OY(aP4a4spY&=)Xdn-c^3-MEhcAWnBu4w>`1Cq-A zrz6lmd$pJOAAynT$+1WL-vm^i{_*_qS=2KkhkXuW`2#vq==AxwyC$h~1wGclro0uT z-`rKpqfl>Q)&AW?9V-7;7Wj!5P>Qg|{%%*MQ4+#6i>nDzvo;}f3t5UIk{=WdwRO-F} literal 0 HcmV?d00001 diff --git a/docs/uptime/index.asciidoc b/docs/uptime/index.asciidoc new file mode 100644 index 0000000000000..8e0b635d3d6a9 --- /dev/null +++ b/docs/uptime/index.asciidoc @@ -0,0 +1,28 @@ +[role="xpack"] +[[xpack-uptime]] += Uptime + +[partintro] +-- +Use the Uptime UI to monitor the status of network endpoints via HTTP/S, TCP, +and ICMP. You will be able to explore status over time, drill into specific monitors, +and view a high-level snapshot of your environment at a selected point in time. + +[float] +== Add monitors +To get started with Uptime monitoring, you'll need to define some monitors and run Heartbeat. +These monitors will provide the data we will be visualizing in the Uptime UI. +See {heartbeat-ref}/heartbeat-configuration.html[Configure Heartbeat] for instructions +on configuring monitors to begin storing Uptime information in your cluster. + +[float] +== Uptime, Heartbeat, and Kibana +For Uptime to work, it is important you use the same major versions of Heartbeat and Kibana. +For example, version 6.7 of Kibana will expect an index of `heartbeat-6*`, +while Kibana 7.0 requires an index of `heartbeat-7*` (containing documents from Heartbeat 7.0). + +-- + +include::overview.asciidoc[] +include::monitor.asciidoc[] +include::security.asciidoc[] diff --git a/docs/uptime/monitor.asciidoc b/docs/uptime/monitor.asciidoc new file mode 100644 index 0000000000000..d54fd02c7c069 --- /dev/null +++ b/docs/uptime/monitor.asciidoc @@ -0,0 +1,54 @@ +[role="xpack"] +[[uptime-monitor]] +== Monitor + +The Monitor page will help you get further insight into the performance +of a specific network endpoint. You'll see a detailed visualization of +the monitor's request duration over time, as well as the `up`/`down` +status over time. + +[float] +=== Status bar + +[role="screenshot"] +image::uptime/images/status-bar.png[Status bar] + +The Status bar displays a quick summary of the latest information +regarding your monitor. You can view its latest status, click a link to +visit the targeted URL, see its most recent request duration, and determine the +amount of time that has elapsed since the last check. + +You can use the Status bar to get a quick summary of current performance, +beyond simply knowing if the monitor is `up` or `down`. + +[float] +=== Monitor charts + +[role="screenshot"] +image::uptime/images/monitor-charts.png[Monitor charts] + +The Monitor charts visualize information over the time specified in the +date range. These charts can help you gain insight into how quickly requests are being resolved +by the targeted endpoint, and give you a sense of how frequently a host or endpoint +was down in your selected timespan. + +The first chart displays request duration information for your monitor. +The area surrounding the line is the range of request time for the corresponding +bucket. The line is the average time. + +Next, is a graphical representation of the check statuses over time. Hover over +the charts to display crosshairs with more specific numeric data. + +[role="screenshot"] +image::uptime/images/crosshair-example.png[Chart crosshair] + +[float] +=== Check history + +[role="screenshot"] +image::uptime/images/check-history.png[Check history view] + +The Check history displays the total count of this monitor's checks for the selected +date range. You can additionally filter the checks by `status` to help find recent problems +on a per-check basis. This table can help you gain some insight into more granular details +about recent individual data points Heartbeat is logging about your host or endpoint. diff --git a/docs/uptime/overview.asciidoc b/docs/uptime/overview.asciidoc new file mode 100644 index 0000000000000..5a421abb32bbc --- /dev/null +++ b/docs/uptime/overview.asciidoc @@ -0,0 +1,61 @@ +[role="xpack"] +[[uptime-overview]] + +== Overview + +The Uptime overview is intended to help you quickly identify and diagnose outages and +other connectivity issues within your network or environment. There is a date range +selection that is global to the Uptime UI; you can use this selection to highlight +an absolute date range, or a relative one, similar to other areas of Kibana. + +[float] +=== Filter bar + +[role="screenshot"] +image::uptime/images/filter-bar.png[Filter bar] + +The filter bar is designed to let you quickly view specific groups of monitors, or even +an individual monitor, if you have defined many. + +This control allows you to use automated filter options, as well as input custom filter +text to select specific monitors by field, URL, ID, and other attributes. + +[float] +=== Snapshot view + +[role="screenshot"] +image::uptime/images/snapshot-view.png[Snapshot view] + +This view is intended to quickly give you a sense of the overall +status of the environment you're monitoring, or a subset of those monitors. +Here, you can see the total number of detected monitors within the selected +Uptime date range. In addition to the total, the counts for the number of monitors +in an `up` or `down` state are displayed, based on the last check reported by Heartbeat +for each monitor. + +Next to the counts, there is a histogram displaying the change over time throughout the +selected date range. + +[float] +=== Monitor list + +[role="screenshot"] +image::uptime/images/monitor-list.png[Monitor list] + +The Monitor list displays information at the level of individual monitors. +The data shown here will flesh out your individual monitors, and provide a quick +way to navigate to a more in-depth visualization for interesting hosts or endpoints. + +This table includes information like the most recent status, when the monitor was last checked, its +ID and URL, its IP address, and a dedicated sparkline showing its check status over time. + +[float] +=== Error list + +[role="screenshot"] +image::uptime/images/error-list.png[Error list] + +The Error list displays aggregations of errors that Heartbeat has logged. Errors are +displayed by Error type, monitor ID, and message. Clicking a monitor's ID will take you +to the corresponding Monitor view, which can provide you richer information about the individual +data points that are resulting in the displayed errors. diff --git a/docs/uptime/security.asciidoc b/docs/uptime/security.asciidoc new file mode 100644 index 0000000000000..94ac0cf70c4ab --- /dev/null +++ b/docs/uptime/security.asciidoc @@ -0,0 +1,73 @@ +[role="xpack"] +[[uptime-security]] + +== Use with Elasticsearch Security + +If you use Elasticsearch security, you'll need to enable certain privileges for users +that would like to access the Uptime app. Below is an example of creating +a user and support role to implement those privileges. + +[float] +=== Create a role + +You'll need a role that lets you access the Heartbeat indices, which by default are `heartbeat-*`. +You can create this with the following request: + +["source","sh",subs="attributes,callouts"] +--------------------------------------------------------------- +PUT /_security/role/uptime +{ "indices" : [ + { + "names" : [ + "heartbeat-*" + ], + "privileges" : [ + "read", + "view_index_metadata" + ], + "field_security" : { + "grant" : [ + "*" + ] + }, + "allow_restricted_indices" : false + } + ], + "applications" : [ + { + "application" : "kibana-.kibana", + "privileges" : [ + "all" + ], + "resources" : [ + "*" + ] + } + ], + "transient_metadata" : { + "enabled" : true + } +} +--------------------------------------------------------------- +// CONSOLE + +[float] +=== Assign the role to a user + +Next, you'll need to create a user with both the `kibana_user`, and `uptime` roles. +You can do this with the following request: + +["source","sh",subs="attributes,callouts"] +--------------------------------------------------------------- +PUT /_security/user/jacknich +{ + "password" : "j@rV1s", + "roles" : [ "uptime", "kibana_user" ], + "full_name" : "Jack Nicholson", + "email" : "jacknich@example.com", + "metadata" : { + "intelligence" : 7 + } +} +--------------------------------------------------------------- +// CONSOLE \ No newline at end of file From 4c152965b697fdcc74fec2d9a80635b5ef9c836a Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Fri, 22 Mar 2019 11:57:06 -0700 Subject: [PATCH 06/96] Fixes broken link (#33724) --- .../monitoring/public/components/cluster/listing/listing.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js b/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js index 911df086c4d33..1b39341a5f7cb 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js +++ b/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js @@ -292,7 +292,7 @@ const handleClickIncompatibleLicense = (scope, clusterName) => { defaultMessage="Need to monitor multiple clusters? {getLicenseInfoLink} to enjoy multi-cluster monitoring." values={{ getLicenseInfoLink: ( - + { ), getLicenseInfoLink: ( - + Date: Fri, 22 Mar 2019 14:53:24 -0500 Subject: [PATCH 07/96] Dashboard typescript (#32703) Typescript Dashboard bits - grid, panel, viewport ui/exit_full_screeen --- package.json | 1 + ...hboard_strings.js => dashboard_strings.ts} | 8 +- .../dashboard/grid/dashboard_grid.test.js | 2 +- .../{dashboard_grid.js => dashboard_grid.tsx} | 153 ++++++++++-------- ...ntainer.js => dashboard_grid_container.ts} | 32 ++-- .../dashboard/grid/{index.js => index.ts} | 0 .../dashboard/panel/dashboard_panel.tsx | 4 +- .../public/dashboard/panel/panel_utils.ts | 15 +- .../public/dashboard/reducers/panels.ts | 2 +- .../public/dashboard/selectors/dashboard.ts | 4 +- .../public/dashboard/selectors/types.ts | 25 +-- .../kibana/public/dashboard/types.ts | 26 +++ ...ard_viewport.js => dashboard_viewport.tsx} | 24 +-- ..._button.js => exit_full_screen_button.tsx} | 41 +++-- .../exit_full_screen/{index.js => index.ts} | 0 yarn.lock | 7 + 16 files changed, 206 insertions(+), 138 deletions(-) rename src/legacy/core_plugins/kibana/public/dashboard/{dashboard_strings.js => dashboard_strings.ts} (92%) rename src/legacy/core_plugins/kibana/public/dashboard/grid/{dashboard_grid.js => dashboard_grid.tsx} (67%) rename src/legacy/core_plugins/kibana/public/dashboard/grid/{dashboard_grid_container.js => dashboard_grid_container.ts} (60%) rename src/legacy/core_plugins/kibana/public/dashboard/grid/{index.js => index.ts} (100%) create mode 100644 src/legacy/core_plugins/kibana/public/dashboard/types.ts rename src/legacy/core_plugins/kibana/public/dashboard/viewport/{dashboard_viewport.js => dashboard_viewport.tsx} (79%) rename src/legacy/ui/public/exit_full_screen/{exit_full_screen_button.js => exit_full_screen_button.tsx} (76%) rename src/legacy/ui/public/exit_full_screen/{index.js => index.ts} (100%) diff --git a/package.json b/package.json index d75f904e4233c..30b46e33b9ea5 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,7 @@ "@kbn/ui-framework": "1.0.0", "@types/json-stable-stringify": "^1.0.32", "@types/lodash.clonedeep": "^4.5.4", + "@types/react-grid-layout": "^0.16.7", "@types/recompose": "^0.30.5", "JSONStream": "1.1.1", "abortcontroller-polyfill": "^1.1.9", diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.js b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.js rename to src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.ts index a0d2af3e9c00a..3ea7cf593687c 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_strings.ts @@ -27,9 +27,13 @@ import { DashboardViewMode } from './dashboard_view_mode'; * end of the title. * @returns {string} A title to display to the user based on the above parameters. */ -export function getDashboardTitle(title, viewMode, isDirty) { +export function getDashboardTitle( + title: string, + viewMode: DashboardViewMode, + isDirty: boolean +): string { const isEditMode = viewMode === DashboardViewMode.EDIT; - let displayTitle; + let displayTitle: string; if (isEditMode && isDirty) { displayTitle = i18n.translate('kbn.dashboard.strings.dashboardUnsavedEditTitle', { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.test.js b/src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.test.js index b71e83159d763..0d9b80763c136 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.test.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.test.js @@ -88,6 +88,6 @@ test('adjusts z-index of focused panel to be higher than siblings', () => { const panelElements = component.find('Connect(InjectIntl(DashboardPanelUi))'); panelElements.first().prop('onPanelFocused')('1'); const [gridItem1, gridItem2] = component.update().findWhere(el => el.key() === '1' || el.key() === '2'); - expect(gridItem1.props.style.zIndex).toEqual('2'); + expect(gridItem1.props.style.zIndex).toEqual(2); expect(gridItem2.props.style.zIndex).toEqual('auto'); }); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.js b/src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.tsx similarity index 67% rename from src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.js rename to src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.tsx index d90b597b1a0c0..bfbf3101c198e 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/grid/dashboard_grid.tsx @@ -17,27 +17,29 @@ * under the License. */ -import React from 'react'; -import PropTypes from 'prop-types'; import { injectI18n } from '@kbn/i18n/react'; -import _ from 'lodash'; -import ReactGridLayout from 'react-grid-layout'; import classNames from 'classnames'; +import _ from 'lodash'; +import React from 'react'; +import ReactGridLayout, { Layout } from 'react-grid-layout'; import 'react-grid-layout/css/styles.css'; import 'react-resizable/css/styles.css'; -import { PanelUtils } from '../panel/panel_utils'; -import { DashboardViewMode } from '../dashboard_view_mode'; -import { DashboardPanel } from '../panel'; +// @ts-ignore +import sizeMe from 'react-sizeme'; +import { EmbeddableFactory } from 'ui/embeddable'; import { toastNotifications } from 'ui/notify'; import { - DashboardConstants, DASHBOARD_GRID_COLUMN_COUNT, DASHBOARD_GRID_HEIGHT, + DashboardConstants, } from '../dashboard_constants'; -import sizeMe from 'react-sizeme'; +import { DashboardViewMode } from '../dashboard_view_mode'; +import { DashboardPanel } from '../panel'; +import { PanelUtils } from '../panel/panel_utils'; +import { PanelState, PanelStateMap, Pre61PanelState } from '../selectors/types'; +import { GridData } from '../types'; -const config = { monitorWidth: true }; let lastValidGridSize = 0; /** @@ -45,7 +47,7 @@ let lastValidGridSize = 0; * taller than the current grid. * see https://github.com/elastic/kibana/issues/14710. */ -function ensureWindowScrollsToBottom(layout, oldResizeItem, l, placeholder, event) { +function ensureWindowScrollsToBottom(event: { clientY: number; pageY: number }) { // The buffer is to handle the case where the browser is maximized and it's impossible for the mouse to move below // the screen, out of the window. see https://github.com/elastic/kibana/issues/14737 const WINDOW_BUFFER = 10; @@ -62,6 +64,14 @@ function ResponsiveGrid({ children, maximizedPanelId, useMargins, +}: { + size: { width: number }; + isViewMode: boolean; + layout: Layout[]; + onLayoutChange: () => void; + children: JSX.Element[]; + maximizedPanelId: string; + useMargins: boolean; }) { // This is to prevent a bug where view mode changes when the panel is expanded. View mode changes will trigger // the grid to re-render, but when a panel is expanded, the size will be 0. Minimizing the panel won't cause the @@ -94,8 +104,7 @@ function ResponsiveGrid({ draggableHandle={isViewMode ? '.doesnt-exist' : '.dshPanel__dragger'} layout={layout} onLayoutChange={onLayoutChange} - measureBeforeMount={false} - onResize={ensureWindowScrollsToBottom} + onResize={({}, {}, {}, {}, event) => ensureWindowScrollsToBottom(event)} > {children} @@ -104,15 +113,43 @@ function ResponsiveGrid({ // Using sizeMe sets up the grid to be re-rendered automatically not only when the window size changes, but also // when the container size changes, so it works for Full Screen mode switches. +const config = { monitorWidth: true }; const ResponsiveSizedGrid = sizeMe(config)(ResponsiveGrid); +interface Props extends ReactIntl.InjectedIntlProps { + panels: PanelStateMap; + getEmbeddableFactory: (panelType: string) => EmbeddableFactory; + dashboardViewMode: DashboardViewMode.EDIT | DashboardViewMode.VIEW; + onPanelsUpdated: (updatedPanels: PanelStateMap) => void; + maximizedPanelId?: string; + useMargins: boolean; +} -class DashboardGridUi extends React.Component { - constructor(props) { +interface State { + focusedPanelIndex?: string; + isLayoutInvalid: boolean; + layout?: GridData[]; +} + +interface PanelLayout extends Layout { + i: string; +} + +class DashboardGridUi extends React.Component { + // A mapping of panelIndexes to grid items so we can set the zIndex appropriately on the last focused + // item. + private gridItems = {} as { [key: string]: HTMLDivElement | null }; + + // A mapping of panel type to embeddable handlers. Because this function reaches out of react and into angular, + // if done in the render method, it appears to be triggering a scope.apply, which appears to be trigging a setState + // call inside TSVB visualizations. Moving the function out of render appears to fix the issue. See + // https://github.com/elastic/kibana/issues/14802 for more info. + // This is probably a better implementation anyway so the handlers are cached. + // @type {Object.} + private embeddableFactoryMap: { [s: string]: EmbeddableFactory } = {}; + + constructor(props: Props) { super(props); - // A mapping of panelIndexes to grid items so we can set the zIndex appropriately on the last focused - // item. - this.gridItems = {}; let isLayoutInvalid = false; let layout; @@ -127,41 +164,36 @@ class DashboardGridUi extends React.Component { }), text: error.message, }); - window.location = `#${DashboardConstants.LANDING_PAGE_PATH}`; + window.location.hash = DashboardConstants.LANDING_PAGE_PATH; } this.state = { focusedPanelIndex: undefined, layout, isLayoutInvalid, }; - - // A mapping of panel type to embeddable handlers. Because this function reaches out of react and into angular, - // if done in the render method, it appears to be triggering a scope.apply, which appears to be trigging a setState - // call inside TSVB visualizations. Moving the function out of render appears to fix the issue. See - // https://github.com/elastic/kibana/issues/14802 for more info. - // This is probably a better implementation anyway so the handlers are cached. - // @type {Object.} - this.embeddableFactoryMap = {}; } - buildLayoutFromPanels() { + public buildLayoutFromPanels(): GridData[] { return _.map(this.props.panels, panel => { // panel version numbers added in 6.1. Any panel without version number is assumed to be 6.0.0 - const panelVersion = panel.version ? PanelUtils.parseVersion(panel.version) : PanelUtils.parseVersion('6.0.0'); + const panelVersion = + 'version' in panel + ? PanelUtils.parseVersion(panel.version) + : PanelUtils.parseVersion('6.0.0'); if (panelVersion.major < 6 || (panelVersion.major === 6 && panelVersion.minor < 1)) { - PanelUtils.convertPanelDataPre_6_1(panel); + panel = PanelUtils.convertPanelDataPre_6_1(panel as Pre61PanelState); } if (panelVersion.major < 6 || (panelVersion.major === 6 && panelVersion.minor < 3)) { - PanelUtils.convertPanelDataPre_6_3(panel, this.props.useMargins); + PanelUtils.convertPanelDataPre_6_3(panel as PanelState, this.props.useMargins); } - return panel.gridData; + return (panel as PanelState).gridData; }); } - createEmbeddableFactoriesMap(panels) { + public createEmbeddableFactoriesMap(panels: PanelStateMap) { Object.values(panels).map(panel => { if (!this.embeddableFactoryMap[panel.type]) { this.embeddableFactoryMap[panel.type] = this.props.getEmbeddableFactory(panel.type); @@ -169,46 +201,46 @@ class DashboardGridUi extends React.Component { }); } - componentWillMount() { + public componentWillMount() { this.createEmbeddableFactoriesMap(this.props.panels); } - componentWillReceiveProps(nextProps) { + public componentWillReceiveProps(nextProps: Props) { this.createEmbeddableFactoriesMap(nextProps.panels); } - onLayoutChange = (layout) => { + public onLayoutChange = (layout: PanelLayout[]) => { const { onPanelsUpdated, panels } = this.props; - const updatedPanels = layout.reduce((updatedPanelsAcc, panelLayout) => { - updatedPanelsAcc[panelLayout.i] = { - ...panels[panelLayout.i], - panelIndex: panelLayout.i, - gridData: _.pick(panelLayout, ['x', 'y', 'w', 'h', 'i']) - }; - return updatedPanelsAcc; - }, []); + const updatedPanels = layout.reduce( + (updatedPanelsAcc, panelLayout) => { + updatedPanelsAcc[panelLayout.i] = { + ...panels[panelLayout.i], + panelIndex: panelLayout.i, + gridData: _.pick(panelLayout, ['x', 'y', 'w', 'h', 'i']), + }; + return updatedPanelsAcc; + }, + {} as PanelStateMap + ); onPanelsUpdated(updatedPanels); }; - onPanelFocused = focusedPanelIndex => { + public onPanelFocused = (focusedPanelIndex: string): void => { this.setState({ focusedPanelIndex }); }; - onPanelBlurred = blurredPanelIndex => { + public onPanelBlurred = (blurredPanelIndex: string): void => { if (this.state.focusedPanelIndex === blurredPanelIndex) { this.setState({ focusedPanelIndex: undefined }); } }; - renderDOM() { - const { - panels, - maximizedPanelId - } = this.props; + public renderDOM() { + const { panels, maximizedPanelId } = this.props; const { focusedPanelIndex } = this.state; // Part of our unofficial API - need to render in a consistent order for plugins. - const panelsInOrder = Object.keys(panels).map(key => panels[key]); + const panelsInOrder = Object.keys(panels).map((key: string) => panels[key] as PanelState); panelsInOrder.sort((panelA, panelB) => { if (panelA.gridData.y === panelB.gridData.y) { return panelA.gridData.x - panelB.gridData.x; @@ -226,10 +258,12 @@ class DashboardGridUi extends React.Component { }); return (

{ this.gridItems[panel.panelIndex] = reactGridItem; }} + ref={reactGridItem => { + this.gridItems[panel.panelIndex] = reactGridItem; + }} > ({ +interface DashboardGridContainerDispatchProps { + onPanelsUpdated(updatedPanels: PanelStateMap): void; +} + +const mapStateToProps = ({ dashboard }: any): any => ({ panels: getPanels(dashboard), dashboardViewMode: getViewMode(dashboard), useMargins: getUseMargins(dashboard), }); -const mapDispatchToProps = (dispatch) => ({ - onPanelsUpdated: updatedPanels => dispatch(updatePanels(updatedPanels)), +const mapDispatchToProps = (dispatch: Dispatch) => ({ + onPanelsUpdated: (updatedPanels: PanelStateMap) => dispatch(updatePanels(updatedPanels)), }); -export const DashboardGridContainer = connect( +export const DashboardGridContainer = connect< + DashboardGridContainerStateProps, + DashboardGridContainerDispatchProps +>( mapStateToProps, mapDispatchToProps )(DashboardGrid); - diff --git a/src/legacy/core_plugins/kibana/public/dashboard/grid/index.js b/src/legacy/core_plugins/kibana/public/dashboard/grid/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/dashboard/grid/index.js rename to src/legacy/core_plugins/kibana/public/dashboard/grid/index.ts diff --git a/src/legacy/core_plugins/kibana/public/dashboard/panel/dashboard_panel.tsx b/src/legacy/core_plugins/kibana/public/dashboard/panel/dashboard_panel.tsx index ceb37dee0da19..0a3cd61a627ad 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/panel/dashboard_panel.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/panel/dashboard_panel.tsx @@ -36,8 +36,8 @@ import { PanelHeader } from './panel_header'; export interface DashboardPanelProps { viewOnlyMode: boolean; - onPanelFocused?: (panelIndex: PanelId) => {}; - onPanelBlurred?: (panelIndex: PanelId) => {}; + onPanelFocused?: (panelIndex: PanelId) => void; + onPanelBlurred?: (panelIndex: PanelId) => void; error?: string | object; destroy: () => void; containerState: ContainerState; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/panel/panel_utils.ts b/src/legacy/core_plugins/kibana/public/dashboard/panel/panel_utils.ts index 52485b48ce307..c4ea15eac5374 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/panel/panel_utils.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/panel/panel_utils.ts @@ -21,7 +21,8 @@ import { i18n } from '@kbn/i18n'; import _ from 'lodash'; import chrome from 'ui/chrome'; import { DEFAULT_PANEL_HEIGHT, DEFAULT_PANEL_WIDTH } from '../dashboard_constants'; -import { GridData, PanelState } from '../selectors'; +import { PanelState } from '../selectors'; +import { GridData } from '../types'; const PANEL_HEIGHT_SCALE_FACTOR = 5; const PANEL_HEIGHT_SCALE_FACTOR_WITH_MARGINS = 4; @@ -34,15 +35,7 @@ export interface SemanticVersion { export class PanelUtils { // 6.1 switched from gridster to react grid. React grid uses different variables for tracking layout - public static convertPanelDataPre_6_1(panel: { - panelIndex: any; // earlier versions allowed panelIndex to be a number or a string - gridData: GridData; - col: number; - row: number; - size_x: number; - size_y: number; - version: string; - }): Partial { + public static convertPanelDataPre_6_1(panel: any): PanelState { ['col', 'row'].forEach(key => { if (!_.has(panel, key)) { throw new Error( @@ -78,7 +71,7 @@ export class PanelUtils { // Need to scale pre 6.3 panels so they maintain the same layout public static convertPanelDataPre_6_3( panel: { - gridData: { w: number; x: number; h: number; y: number }; + gridData: GridData; version: string; }, useMargins: boolean diff --git a/src/legacy/core_plugins/kibana/public/dashboard/reducers/panels.ts b/src/legacy/core_plugins/kibana/public/dashboard/reducers/panels.ts index 172110df340a3..f4961a61c01b8 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/reducers/panels.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/reducers/panels.ts @@ -57,7 +57,7 @@ const setPanelTitle = (panels: PanelStateMap, payload: SetPanelTitleActionPayloa }, }); -const setPanels = (panels: PanelStateMap, newPanels: PanelStateMap) => _.cloneDeep(newPanels); +const setPanels = ({}, newPanels: PanelStateMap) => _.cloneDeep(newPanels); export const panelsReducer: Reducer = (panels = {}, action): PanelStateMap => { switch ((action as PanelActions).type) { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/selectors/dashboard.ts b/src/legacy/core_plugins/kibana/public/dashboard/selectors/dashboard.ts index c2a9c245838a7..39ff7e51c689c 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/selectors/dashboard.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/selectors/dashboard.ts @@ -38,10 +38,10 @@ import { PanelStateMap, } from './types'; -export const getPanels = (dashboard: DashboardState): PanelStateMap => dashboard.panels; +export const getPanels = (dashboard: DashboardState): Readonly => dashboard.panels; export const getPanel = (dashboard: DashboardState, panelId: PanelId): PanelState => - getPanels(dashboard)[panelId]; + getPanels(dashboard)[panelId] as PanelState; export const getPanelType = (dashboard: DashboardState, panelId: PanelId): string => getPanel(dashboard, panelId).type; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/selectors/types.ts b/src/legacy/core_plugins/kibana/public/dashboard/selectors/types.ts index 27d75875e40a8..165f06d9037ae 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/selectors/types.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/selectors/types.ts @@ -19,7 +19,9 @@ import { EmbeddableMetadata, Filters, Query, RefreshConfig, TimeRange } from 'ui/embeddable'; import { DashboardViewMode } from '../dashboard_view_mode'; +import { GridData } from '../types'; +export type DashboardViewMode = DashboardViewMode; export interface ViewState { readonly viewMode: DashboardViewMode; readonly isFullScreenMode: boolean; @@ -33,14 +35,6 @@ export interface ViewState { readonly filters: Filters; } -export interface GridData { - readonly w: number; - readonly h: number; - readonly x: number; - readonly y: number; - readonly i: string; -} - export type PanelId = string; export type SavedObjectId = string; @@ -65,8 +59,21 @@ export interface EmbeddableReduxState { readonly lastReloadRequestTime: number; } +export interface Pre61PanelState { + size_x: number; + size_y: number; + row: number; + col: number; + panelIndex: any; // earlier versions allowed this to be number or string + id: string; + type: string; + // Embeddableconfig didn't actually exist on older panel states but `migrate_app_state.js` handles + // stuffing it on. + embeddableConfig: any; +} + export interface PanelStateMap { - readonly [panelId: string]: PanelState; + [panelId: string]: PanelState | Pre61PanelState; } export interface EmbeddablesMap { diff --git a/src/legacy/core_plugins/kibana/public/dashboard/types.ts b/src/legacy/core_plugins/kibana/public/dashboard/types.ts new file mode 100644 index 0000000000000..eb76d73af7a58 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/types.ts @@ -0,0 +1,26 @@ +/* + * 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 interface GridData { + w: number; + h: number; + x: number; + y: number; + i: string; +} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/viewport/dashboard_viewport.js b/src/legacy/core_plugins/kibana/public/dashboard/viewport/dashboard_viewport.tsx similarity index 79% rename from src/legacy/core_plugins/kibana/public/dashboard/viewport/dashboard_viewport.js rename to src/legacy/core_plugins/kibana/public/dashboard/viewport/dashboard_viewport.tsx index bc037ed908b9d..8e34b50a0383d 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/viewport/dashboard_viewport.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/viewport/dashboard_viewport.tsx @@ -18,9 +18,9 @@ */ import React from 'react'; -import PropTypes from 'prop-types'; -import { DashboardGrid } from '../grid'; +import { EmbeddableFactory } from 'ui/embeddable'; import { ExitFullScreenButton } from 'ui/exit_full_screen'; +import { DashboardGrid } from '../grid'; export function DashboardViewport({ maximizedPanelId, @@ -31,6 +31,15 @@ export function DashboardViewport({ useMargins, isFullScreenMode, onExitFullScreenMode, +}: { + maximizedPanelId: string; + getEmbeddableFactory: (panelType: string) => EmbeddableFactory; + panelCount: number; + title: string; + description: string; + useMargins: boolean; + isFullScreenMode: boolean; + onExitFullScreenMode: () => void; }) { return (
- { isFullScreenMode && } + {isFullScreenMode && } ); } - -DashboardViewport.propTypes = { - getEmbeddableFactory: PropTypes.func, - maximizedPanelId: PropTypes.string, - panelCount: PropTypes.number, - title: PropTypes.string, - description: PropTypes.string, - useMargins: PropTypes.bool.isRequired, -}; diff --git a/src/legacy/ui/public/exit_full_screen/exit_full_screen_button.js b/src/legacy/ui/public/exit_full_screen/exit_full_screen_button.tsx similarity index 76% rename from src/legacy/ui/public/exit_full_screen/exit_full_screen_button.js rename to src/legacy/ui/public/exit_full_screen/exit_full_screen_button.tsx index 9e985426e8f41..4fc17a7dbca38 100644 --- a/src/legacy/ui/public/exit_full_screen/exit_full_screen_button.js +++ b/src/legacy/ui/public/exit_full_screen/exit_full_screen_button.tsx @@ -17,39 +17,37 @@ * under the License. */ +import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; import chrome from 'ui/chrome'; -import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; -import { - KuiButton, -} from '@kbn/ui-framework/components'; +// @ts-ignore +import { KuiButton } from '@kbn/ui-framework/components'; -import { - keyCodes, - EuiScreenReaderOnly, -} from '@elastic/eui'; +import { EuiScreenReaderOnly, keyCodes } from '@elastic/eui'; -class ExitFullScreenButtonUi extends PureComponent { +interface Props extends ReactIntl.InjectedIntlProps { + onExitFullScreenMode: () => void; +} - onKeyDown = (e) => { +class ExitFullScreenButtonUi extends PureComponent { + public onKeyDown = (e: KeyboardEvent) => { if (e.keyCode === keyCodes.ESCAPE) { this.props.onExitFullScreenMode(); } }; - componentWillMount() { + public componentWillMount() { document.addEventListener('keydown', this.onKeyDown, false); chrome.setVisible(false); } - componentWillUnmount() { + public componentWillUnmount() { document.removeEventListener('keydown', this.onKeyDown, false); chrome.setVisible(true); } - render() { + public render() { const { intl } = this.props; return ( @@ -62,9 +60,7 @@ class ExitFullScreenButtonUi extends PureComponent { />

-
+
- + - +
@@ -89,8 +88,4 @@ class ExitFullScreenButtonUi extends PureComponent { } } -ExitFullScreenButtonUi.propTypes = { - onExitFullScreenMode: PropTypes.func.isRequired, -}; - export const ExitFullScreenButton = injectI18n(ExitFullScreenButtonUi); diff --git a/src/legacy/ui/public/exit_full_screen/index.js b/src/legacy/ui/public/exit_full_screen/index.ts similarity index 100% rename from src/legacy/ui/public/exit_full_screen/index.js rename to src/legacy/ui/public/exit_full_screen/index.ts diff --git a/yarn.lock b/yarn.lock index 6236beffd0ab7..02a508c614501 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2183,6 +2183,13 @@ dependencies: "@types/react" "*" +"@types/react-grid-layout@^0.16.7": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-0.16.7.tgz#53d5f5034deb0c60e25a0fa578141e9a0982011f" + integrity sha512-A3tW9xySd03KGONkp8gP4+QRLuT1Mcx++m0hO0nZIM4H/Qwz8GsiDv+9okbmHk5HcsHwY5Jdsn6Cv50hwoNG+A== + dependencies: + "@types/react" "*" + "@types/react-intl@^2.3.15": version "2.3.17" resolved "https://registry.yarnpkg.com/@types/react-intl/-/react-intl-2.3.17.tgz#e1fc6e46e8af58bdef9531259d509380a8a99e8e" From b647f2ba6aff6af80d677d099d3345b12750b924 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 22 Mar 2019 14:46:04 -0700 Subject: [PATCH 08/96] [reporting/extract] replace fixtures that look like source (#33739) The fixtures used by reporting's `extract()` tests have tripped me and others up several times because from the outside they look and behave like source files, but require updating archive fixtures whenever the source is touched. The source of this file is irrelevant though, since the tests are just making sure that the extraction is accurate. This PR updates the fixture to a markdown file with Lorem Ipsum in it, so it won't look relevant to people making broad strokes changes to files like https://github.com/elastic/kibana/pull/33733 --- .../__fixtures__/extract_test_file.js | 73 ------------------ .../__fixtures__/extract_test_file.js.bz2 | Bin 1058 -> 0 bytes .../__fixtures__/extract_test_file.js.tar.bz2 | Bin 1162 -> 0 bytes .../__fixtures__/extract_test_file.js.zip | Bin 1119 -> 0 bytes .../extract/__tests__/__fixtures__/file.md | 9 +++ .../__tests__/__fixtures__/file.md.bz2 | Bin 0 -> 1205 bytes .../__tests__/__fixtures__/file.md.tar.bz2 | Bin 0 -> 1319 bytes .../__tests__/__fixtures__/file.md.zip | Bin 0 -> 1419 bytes .../browsers/extract/__tests__/extract.js | 9 ++- 9 files changed, 14 insertions(+), 77 deletions(-) delete mode 100644 x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js delete mode 100644 x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.bz2 delete mode 100644 x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.tar.bz2 delete mode 100644 x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.zip create mode 100644 x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md create mode 100644 x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.bz2 create mode 100644 x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.tar.bz2 create mode 100644 x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.zip diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js deleted file mode 100644 index 33a83f01f53ea..0000000000000 --- a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js +++ /dev/null @@ -1,73 +0,0 @@ -/* eslint-disable @kbn/license-header/require-license-header */ -export const search = { - _index: '.kibana', - _type: 'search', - _id: 'mock-search', - _version: 1, - found: true, - _source: { - title: 'to IN', - description: '', - hits: 0, - columns: [ - '_source' - ], - sort: [ - '@timestamp', - 'desc' - ], - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: '{\'index\':\'logstash-*\',\'query\':{\'query_string\':{\'query\':\'geo.dest: IN\',' - + '\'analyze_wildcard\':true}},\'filter\':[],\'highlight\':{\'pre_tags\':[\'@kibana-highlighted-field@\'],' - + '\'post_tags\':[\'@/kibana-highlighted-field@\'],\'fields\':{\'*\':{}},\'require_field_match\':false,' - + '\'fragment_size\':2147483647}}' - } - } -}; - -export const visualization = { - _index: '.kibana', - _type: 'visualization', - _id: 'mock-visualization', - _version: 1, - found: true, - _source: { - title: 'dem line', - visState: '{\'title\':\'New Visualization\',\'type\':\'line\',\'params\':{\'shareYAxis\':true,\'addTooltip\':true,' - + '\'addLegend\':true,\'showCircles\':true,\'smoothLines\':false,\'interpolate\':\'linear\',\'scale\':\'linear\',' - + '\'drawLinesBetweenPoints\':true,\'radiusRatio\':9,\'times\':[],\'addTimeMarker\':false,\'defaultYExtents\':false,' - + '\'setYExtents\':false,\'yAxis\':{}},\'aggs\':[{\'id\':\'1\',\'type\':\'count\',\'schema\':\'metric\',\'params\':{}},' - + '{\'id\':\'2\',\'type\':\'date_histogram\',\'schema\':\'segment\',\'params\':{\'field\':\'@timestamp\',\'interval\':\'auto\',' - + '\'customInterval\':\'2h\',\'min_doc_count\':1,\'extended_bounds\':{}}}],\'listeners\':{}}', - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: '{\'index\':\'logstash-*\',\'query\':{\'query_string\':{\'query\':\'*\',\'analyze_wildcard\':true}},\'filter\':[]}' - } - } -}; - -export const dashboard = { - _index: '.kibana', - _type: 'dashboard', - _id: 'mock-dashboard', - _version: 1, - found: true, - _source: { - title: 'example dashboard', - hits: 0, - description: '', - panelsJSON: '[{\'id\':\'mock-visualization\',\'type\':\'visualization\',\'panelIndex\':1,\'size_x\':3,\'size_y\':5,' - + '\'col\':1,\'row\':1},{\'id\':\'mock-search\',\'type\':\'search\',\'panelIndex\':2,\'size_x\':7,\'size_y\':4,\'col\':4,' - + '\'row\':1,\'columns\':[\'_source\'],\'sort\':[\'@timestamp\',\'desc\']}]', - optionsJSON: '{\'darkTheme\':false}', - uiStateJSON: '{}', - version: 1, - timeRestore: false, - kibanaSavedObjectMeta: { - searchSourceJSON: '{\'filter\':[{\'query\':{\'query_string\':{\'query\':\'*\',\'analyze_wildcard\':true}}}]}' - } - } -}; diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.bz2 b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.bz2 deleted file mode 100644 index d4f349ee7dba9ac13985ab422e1b2253002e9103..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1058 zcmV+-1l{{WT4*^jL0KkKS&{TXivR(U-+)jMK%f8mdNtL_C^U&ZH9u5(LFAfxfDHfuGynl1DWnPNFoq~? zO&VeYLq>oA0OpLCm;jiJ2-5-#MhTMuj1fpiNT=zfn-fvAPf!Cu000J_l4>Txtn34`gpoS5oqa1{26B}SA(3?YJ18dA~9_!j;T(sK5 zyhA*SF;ZfsIq2uDH7^}eb@x=Yhjr0`D(Y1{9X%If@nS>cS+|GiOjtAnG*=dle;k&9 zoHwH6!)#;gvd7ri)8$*szo~I1pf-Ms3t29*Yg*tygKE;Hi37{#I-X2>n&v4)_wId5 zxAK!!mW8=|0?S)%^CRepg`-!7r ziJRkgILuERWi^c3Vxz@|I98}$+GbzM%BVFy#hmFf@!hwrHeVqpYEe#_a;k*Ln@x=s zK^tk2g%YR+(NCMGwe8fBaAVt;<{EKdHZ-%kgA001hjFH@#;HZ;13v-jS{3Wc*DvT3 zt@TLBfZ+;OO7_w?B;|Aef8k26vYz+@Dch_M&KsFnt2BTh5CU)!A@vK^u~-=Cm#_{L zn~ot=3J?!M5ix^O7kYV_lf!})A4n3>!qSQsy1alOkVPCg*d(-HAY3jFqS;8MaA{VN zdh9G<2L|)B?D5C;`kPWIgSVqGpvaLtijz3iHG<(`0rV>*Mal;G>=*oUu{QS=Dvk`G z;@1t4g_F*$H*FP8^EN|jz~hUlszwAqnW*39GOSJFIY8aYRlqz6&e7h@$4YLqVxhdu z%4Z!{Au=Xj_>9_1sFVZcrw5ZvDiNt;Mh=G3own6+S#Zt_si@Vs7qDfbOOG0pUlSC$ zD=Ju1)Ews)z?SksQlurSwg#}@H7{sQ_Yh73jU=4cx+1Az%iJD#=8)Nq7i>SgCl>TA zkOD65J$9?4i*IqjxIFA~ZZo*+F^A9vF5b|+#z<-oLIPQBqqArd0?@H(OOKZgVX3^C z)&j|Ll2Fcxwr0(NR+qOvgk zjTo9m&#ILntC@`%_C#Zvuy$#;SKy?^U>mg7wa$Z!!eFqLU`yaAGf-s4rO0xWW cU%F?J9}cx@KDJkmhd<)(NT&)C5Y7-Yzch zcZY9voUZL_xxpla1y9ogr>XihO{G02skHS&O#lFCqiO>|kpO~C8$(Ss8UdgH00001 zAtcgG8Zi@0O{8g{27qV)4F-TCRSb_)X*2^&fB*r2nE|6f01-tA=^7d->UwE5nom#w z27m^Epc$0=`+4*4x&sXWYpqI6RS^nA3j-vf8ytvcN2P(6l$mN}h5_8-;E8b;+`8vk zP>SFH4XddLQXw;2Cb%7+4sL#L#t-xv75)XAVFlR}(=fTz73oRUdU}HRuT(YJ@^i*% zxW#qdNuK%AM!I51I9h@jMv{zj5ui+MfSW>X4U7&au6IYlc9_>CHnVrgXOTuKOjM^G z9CfCp$5dMOsfGi!qXJc_RO033wmvLS`E5HnGm#gK0Pnh0x3|x$ei`ov3e%%}%x%2!oWcb`xEUI~@oi z*LWGQnB-A?Hi-m@dMzlC!B$Au&`@rK2+BkOg#(%pD1(GNmprAi(m2otW?sCxu*mZj zTHVS$5t74B{qs!JtR&a9?U}2pO&i86*&D#!F?k~?tcLytM~-Zet+-vZ%)JXLpxb_> zoaHj^+kcrhUP4X@MLKE9suLn@HZ)ZPZKg&PN}wA>KF1-2+oD)Zab4ol?^Z|*rvf@|+U|j3b`Jo}6U6141D>HCa^8u3O z;ZT1tjjn1`z(8Otff649W!rTbREeS|csggJrF01UrZgc`ixLrGDy>a`Ry=mpXOeg;D-Q2ITty#m#_KUz#>-G6%&t`9IpUtx6!BR0ph| zqPNm^3srl!t+{X~yum2{rR$u93nsigyFhm@^U|F<$5W2WE#IVf@yrUTIbo-xmP(vp z5=`15XtrwNlMhFB3LkP<-W7iAXh)O5bGQDJ(e)lnS9A-V4}a(3A#%v=UCrCICUNUi zixMgrZ(Uf#r5KpD(8})a9nO!e7R$>I_^Iz#G(Dd1La9>dRN1=?^>gOWOW4<6_~ewh z`(q0sBWIVn{AQ0cwEOb11HP}Q;OXx)>zW?v{b-NTgxfPD)#@vn>H-<6oflag$~p3v zS;bf{!b{YdJ^I$NgCBzRcr>QO#6H%19;x>sz2=9PV^YSlwN`z6e~z+wDZceN}yS!Jg_5F@@D(#JdYo@hTf<=UZ`y7|%{ zKHf?xIw5uKYGH}I*Rx7bWB(lMZD;N#E|2~#@;m2{X|cu%VX=nh+25j?K2CeEx?uO+ z0-o2?pTtPdTo`Y^j_vs0t#P|o7K*Lbeby5b{%%EqRh0D2wY5>o0fjfrZk?T*eDHM3 zNfXZN((f1WV(&-p@E4zN zw<-Q`S@hl8?Chl-`%|mBuIEV1P!|92^gi#^>O{Mnle(rUl&r|hX1Mk}e)^%;TH-Ga zOpY6!eE05%+&3}y+YRNiSzdxYQ|H`Vp0;{=({l&$-Kwt}-feUIetW^Xy3@-sJ2pAZEnVDfpBZ!4P`?Er_KU&rg V@MdKL>0t!IC?NeFSd1_*006}S07?J= diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md new file mode 100644 index 0000000000000..ab5ba94b31d97 --- /dev/null +++ b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md @@ -0,0 +1,9 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam accumsan eleifend dolor, lacinia ullamcorper metus. Nam sollicitudin, elit ut vehicula sagittis, risus ligula tristique arcu, non hendrerit dolor elit ac urna. Fusce congue accumsan massa vitae congue. Phasellus tristique leo sed sapien ultricies faucibus. Vivamus ultrices sem at tellus fringilla, eget lacinia tellus ullamcorper. Donec pulvinar pretium ante, ut cursus sem varius sed. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque justo risus, aliquam tempus bibendum vel, dignissim vitae est. Suspendisse hendrerit dictum tincidunt. Vestibulum sed odio convallis, pretium ligula luctus, dictum metus. Nullam scelerisque risus id nisl venenatis, non volutpat erat ornare. Suspendisse quam nunc, sollicitudin eget sodales vehicula, lacinia ac ligula. Fusce viverra, metus posuere laoreet molestie, tellus dui pharetra est, at porta nulla est at nisi. Aliquam ut elit orci. Etiam ac venenatis ex. Praesent est lacus, dictum sit amet ornare id, vulputate sit amet odio. + +Curabitur pretium viverra nibh, interdum dapibus turpis tincidunt at. Duis ac libero ultricies, maximus metus sit amet, rutrum sapien. Suspendisse potenti. Praesent a massa non nisl ullamcorper congue nec et turpis. Phasellus mattis, quam in tempor dictum, quam dui commodo velit, vel rutrum urna libero rhoncus felis. Nunc ullamcorper ligula fringilla ultricies bibendum. Nulla facilisi. Vestibulum pulvinar justo nisl, vel interdum urna venenatis ornare. Nunc luctus malesuada metus, ac luctus lorem fringilla faucibus. Cras ullamcorper neque ac sem facilisis feugiat. Maecenas tempor nisl arcu, eget dignissim ex faucibus sed. + +Ut vel ex ipsum. Aenean interdum a tortor non convallis. Curabitur viverra aliquam laoreet. Aliquam commodo ex ut dui venenatis, non pretium est feugiat. Integer nunc nisl, sodales nec tristique nec, finibus sed felis. In metus purus, interdum at congue nec, vehicula ac odio. Mauris in ultrices tellus. Pellentesque eget laoreet dui. Proin sollicitudin orci non odio ullamcorper bibendum. Nam neque tortor, laoreet at egestas in, viverra sit amet orci. Mauris facilisis non ipsum in accumsan. + +Proin luctus, felis at ultricies vulputate, neque lectus convallis odio, in laoreet lorem nulla eget enim. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed at justo elementum, laoreet est pretium, consequat quam. Mauris accumsan consectetur tellus a semper. Nam dictum justo vitae sapien congue, quis porta orci condimentum. Sed dapibus, ex sed luctus dapibus, magna sapien euismod nisl, id tincidunt erat lorem vel purus. Vivamus consectetur eros nec facilisis pellentesque. + +Duis et rutrum eros. Cras id bibendum nisl. Aenean pulvinar non tortor a varius. Pellentesque at auctor lacus. Phasellus aliquet massa elit, vitae bibendum nunc interdum sed. Aenean a consequat tellus, nec pretium odio. Aenean et nisl facilisis, eleifend urna vel, tempor enim. Curabitur sapien sem, rutrum eu velit id, ullamcorper cursus justo. Donec eget magna nec enim iaculis placerat. diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.bz2 b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..c49e1b504ef1203428d1a495a5f2729159fae88d GIT binary patch literal 1205 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 du+uQzT%rMl)RHcO+AV2@e=U-0+RkTG9Xj literal 0 HcmV?d00001 diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.zip b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.zip new file mode 100644 index 0000000000000000000000000000000000000000..a0836ba67abe492be4c4048b633445769be8fc11 GIT binary patch literal 1419 zcmV;61$6pQO9KQH00ICA0LyT8P6iOVspkX$02~Ye00#gZ0A^`yWiD-GRa6N815Hkq zT!c=QTy=O0009K`0RR956aWAKeO61Z+%^#0zf&=`dt%Ju(F>JAQXzZ`*9f6W(Sr)q6T@Os7i*+tz$Df8)Cxy=Tj%?i@DV z)6`;~?t^XhWHLRt6waGToNG3oAF^EVtKeW~DA~H15QF)^p~)p|&ozavfBaYWEW5i9$9wTyi>J&mtwy0lMZ~; zp5ajjp;Sz1d%Y)c#^3-&K3ti!^v4%=ZsxZboHb|lPY#sKnOtG$LZP@#*s(PU7jnRp z66=5WoB53AX~&D${vhvirJaEA02uHfpLd1N#0O`?;e!7QfH=I8rQUyQF0oO*8R`-j zcbquu&UY}4U7pTwX6HxXocZW1x(ri%t@*?|Sa(-h*cNCZ7k4(@a@>X5>Ck0xP~3nHvpxCgQo~qFc2xw5GtjQ9p;?;QYgE~DXi`Cx?YcsB@jr##{6S)j^bqfH#&^Y?M zQvupG^Q``?h2WR<6x!V0-agetca|g=;`Azk>i)68Qr&|)I^`}sR1*SYiH-tb@XERI zb$2PQb^=xOgQbfaWh;YHElI#?|Gmm}#)8WDQY7`h7P-{|*X-#LARUIX8oX=MAJpDo}QYcuaiieA;Q z#OE;bp(f#el~gWX-PTA1!`h4>w5FEgbLO-p`6_i9qVY0`n%9);4Xh6fk~Y)Zf~eB7yq(qtalfiG3rTKq?!!bY!TQb( z)J?(mz~03FV$WXcTt4U#Xzc2+8=9pX9+P(EyN=aHwzRCedfkq$l^`EmlPp7=7vI7M zIwwF@4_5i02M>;%_YeUw6JZ9Tc&ldu^=r~keF2;hS6yR2AnV_q^oTr=^THV zd+pMw78zGe?Sm$){>1i%!G$!?2~tGM+uMIoO928N0~7!P00;ofaCS}x5W1=71ONaW z3;+NJ02lxO000010001_fdBvi0A^`yWiD-GRa6B415HkqTy=O0009K`0RR956aWAK ZP)h{{000000RRC2O#lD@C Date: Fri, 22 Mar 2019 16:48:38 -0500 Subject: [PATCH 09/96] [optimizer] Make thread-loader worker count configurable (#33731) * [optimizer] Make thread-loader worker count configurable * Make minimum 1 --- src/legacy/server/config/schema.js | 1 + src/optimize/base_optimizer.js | 5 +++++ src/optimize/index.js | 1 + src/optimize/watch/optmzr_role.js | 3 ++- 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/legacy/server/config/schema.js b/src/legacy/server/config/schema.js index 97d7da4d8f192..0d136d831a6b3 100644 --- a/src/legacy/server/config/schema.js +++ b/src/legacy/server/config/schema.js @@ -197,6 +197,7 @@ export default () => Joi.object({ ) .default('#cheap-source-map'), }), + workers: Joi.number().min(1), profile: Joi.boolean().default(false) }).default(), status: Joi.object({ diff --git a/src/optimize/base_optimizer.js b/src/optimize/base_optimizer.js index deb914cf6cbe9..b260f57df3311 100644 --- a/src/optimize/base_optimizer.js +++ b/src/optimize/base_optimizer.js @@ -59,6 +59,7 @@ export default class BaseOptimizer { this.logWithMetadata = opts.logWithMetadata || (() => null); this.uiBundles = opts.uiBundles; this.profile = opts.profile || false; + this.workers = opts.workers; switch (opts.sourceMaps) { case true: @@ -139,6 +140,10 @@ export default class BaseOptimizer { } getThreadPoolCpuCount() { + if (this.workers) { + return this.workers; + } + const cpus = os.cpus(); if (!cpus) { // sometimes this call returns undefined so we fall back to 1: https://github.com/nodejs/node/issues/19022 diff --git a/src/optimize/index.js b/src/optimize/index.js index 9cc62a6e1626d..e5f1e84d9733f 100644 --- a/src/optimize/index.js +++ b/src/optimize/index.js @@ -68,6 +68,7 @@ export default async (kbnServer, server, config) => { uiBundles, profile: config.get('optimize.profile'), sourceMaps: config.get('optimize.sourceMaps'), + workers: config.get('optimize.workers'), }); server.log( diff --git a/src/optimize/watch/optmzr_role.js b/src/optimize/watch/optmzr_role.js index d6b12f8c944b6..648d1b9f4e50d 100644 --- a/src/optimize/watch/optmzr_role.js +++ b/src/optimize/watch/optmzr_role.js @@ -32,13 +32,14 @@ export default async (kbnServer, kibanaHapiServer, config) => { uiBundles: kbnServer.uiBundles, profile: config.get('optimize.profile'), sourceMaps: config.get('optimize.sourceMaps'), + workers: config.get('optimize.workers'), prebuild: config.get('optimize.watchPrebuild'), watchCache: new WatchCache({ logWithMetadata, outputPath: config.get('path.data'), dllsPath: DllCompiler.getRawDllConfig().outputPath, cachePath: resolve(kbnServer.uiBundles.getCacheDirectory(), '../'), - }) + }), }); const server = new WatchServer( From 53ab06898b51de8772cb0a7fedb38846c890f09e Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Fri, 22 Mar 2019 16:48:53 -0500 Subject: [PATCH 10/96] Exclude ambient type definitions from checkTsProjects (#33737) --- src/dev/file.ts | 4 ++++ src/dev/typescript/get_ts_project_for_absolute_path.ts | 6 ++++-- src/dev/typescript/run_check_ts_projects_cli.ts | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/dev/file.ts b/src/dev/file.ts index b4283de3dbe4d..5dc66016e1e55 100644 --- a/src/dev/file.ts +++ b/src/dev/file.ts @@ -48,6 +48,10 @@ export class File { return this.ext === '.ts' || this.ext === '.tsx'; } + public isTypescriptAmbient() { + return this.path.endsWith('.d.ts'); + } + public isSass() { return this.ext === '.sass' || this.ext === '.scss'; } diff --git a/src/dev/typescript/get_ts_project_for_absolute_path.ts b/src/dev/typescript/get_ts_project_for_absolute_path.ts index 409d18bed6f5e..843743fd7a3b6 100644 --- a/src/dev/typescript/get_ts_project_for_absolute_path.ts +++ b/src/dev/typescript/get_ts_project_for_absolute_path.ts @@ -17,9 +17,10 @@ * under the License. */ -import { relative } from 'path'; +import { relative, resolve } from 'path'; import { REPO_ROOT } from '../constants'; +import { File } from '../file'; import { PROJECTS } from './projects'; /** @@ -33,6 +34,7 @@ import { PROJECTS } from './projects'; */ export function getTsProjectForAbsolutePath(path: string) { const relPath = relative(REPO_ROOT, path); + const file = new File(resolve(REPO_ROOT, path)); const projects = PROJECTS.filter(p => p.isAbsolutePathSelected(path)); if (!projects.length) { @@ -41,7 +43,7 @@ export function getTsProjectForAbsolutePath(path: string) { ); } - if (projects.length !== 1) { + if (projects.length !== 1 && !file.isTypescriptAmbient()) { const configPaths = projects.map(p => `"${relative(REPO_ROOT, p.tsConfigPath)}"`); const pathsMsg = `${configPaths.slice(0, -1).join(', ')} or ${ diff --git a/src/dev/typescript/run_check_ts_projects_cli.ts b/src/dev/typescript/run_check_ts_projects_cli.ts index d9c1259882c56..d4a4b5dee5fa3 100644 --- a/src/dev/typescript/run_check_ts_projects_cli.ts +++ b/src/dev/typescript/run_check_ts_projects_cli.ts @@ -55,7 +55,7 @@ export async function runCheckTsProjectsCli() { if (projects.length === 0) { isNotInTsProject.push(file); } - if (projects.length > 1) { + if (projects.length > 1 && !file.isTypescriptAmbient()) { isInMultipleTsProjects.push(file); } } From ce96df1e701066db5bc93c52bd06bb64bc374d68 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Fri, 22 Mar 2019 15:04:15 -0700 Subject: [PATCH 11/96] [DOCS] Adds notable highlights tags (#33675) --- docs/release-notes/highlights-8.0.0.asciidoc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/highlights-8.0.0.asciidoc b/docs/release-notes/highlights-8.0.0.asciidoc index ecb6e95d28f45..959a238b5f1a5 100644 --- a/docs/release-notes/highlights-8.0.0.asciidoc +++ b/docs/release-notes/highlights-8.0.0.asciidoc @@ -6,4 +6,12 @@ coming[8.0.0] -See also <> and <>. \ No newline at end of file +See also <> and <>. + + +//NOTE: The notable-highlights tagged regions are re-used in the +//Installation and Upgrade Guide + +// tag::notable-highlights[] + +// end::notable-highlights[] \ No newline at end of file From 96c39b695d16d13677fea7e28d38c812b8468dbd Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 22 Mar 2019 15:13:08 -0700 Subject: [PATCH 12/96] [jest/integration] set default test timeout to 30 seconds (#33718) * [jest/integration] set default test timeout to 30 seconds * move into dev/jest/setup directory --- src/dev/jest/config.integration.js | 3 +++ src/dev/jest/setup/after_env.integration.js | 25 ++++++++++++++++++++ x-pack/test_utils/jest/config.integration.js | 3 +++ 3 files changed, 31 insertions(+) create mode 100644 src/dev/jest/setup/after_env.integration.js diff --git a/src/dev/jest/config.integration.js b/src/dev/jest/config.integration.js index 884172f646c67..8348b7594961f 100644 --- a/src/dev/jest/config.integration.js +++ b/src/dev/jest/config.integration.js @@ -32,4 +32,7 @@ export default { 'default', ['/src/dev/jest/junit_reporter.js', { reportName: 'Jest Integration Tests' }], ], + setupFilesAfterEnv: [ + '/src/dev/jest/setup/after_env.integration.js' + ] }; diff --git a/src/dev/jest/setup/after_env.integration.js b/src/dev/jest/setup/after_env.integration.js new file mode 100644 index 0000000000000..7a2e7b8ab31c3 --- /dev/null +++ b/src/dev/jest/setup/after_env.integration.js @@ -0,0 +1,25 @@ +/* + * 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-env jest */ + +/** + * Set the default timeout for the integration test suite to 30 seconds + */ +jest.setTimeout(30 * 1000); diff --git a/x-pack/test_utils/jest/config.integration.js b/x-pack/test_utils/jest/config.integration.js index 9b3a764855128..242942594d985 100644 --- a/x-pack/test_utils/jest/config.integration.js +++ b/x-pack/test_utils/jest/config.integration.js @@ -19,4 +19,7 @@ export default { 'default', ['/../src/dev/jest/junit_reporter.js', { reportName: 'Jest Integration Tests' }], ], + setupFilesAfterEnv: [ + '/../src/dev/jest/setup/after_env.integration.js' + ] }; From 29badf76556232a512d559c008e62c951a6c98a7 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 22 Mar 2019 15:15:21 -0700 Subject: [PATCH 13/96] [ftr/dashboard] wait for importFile() to finish (#33723) * [ftr/dashboard] wait for importFile() to finish * move waitUntilLoadingHasFinished() into importFile() call * remove unnecessary page object --- test/functional/apps/management/_import_objects.js | 13 ------------- .../apps/management/_mgmt_import_saved_objects.js | 1 - test/functional/page_objects/settings_page.js | 3 +++ 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/test/functional/apps/management/_import_objects.js b/test/functional/apps/management/_import_objects.js index d7659e6859e77..7fc7bf276289b 100644 --- a/test/functional/apps/management/_import_objects.js +++ b/test/functional/apps/management/_import_objects.js @@ -41,7 +41,6 @@ export default function ({ getService, getPageObjects }) { it('should import saved objects', async function () { await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects.json')); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.clickImportDone(); await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); const objects = await PageObjects.settings.getSavedObjectsInTable(); @@ -52,7 +51,6 @@ export default function ({ getService, getPageObjects }) { it('should provide dialog to allow the importing of saved objects with index pattern conflicts', async function () { await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects-conflicts.json')); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.associateIndexPattern('d1e4c910-a2e6-11e7-bb30-233be9be6a15', 'logstash-*'); await PageObjects.settings.clickConfirmChanges(); await PageObjects.header.waitUntilLoadingHasFinished(); @@ -70,7 +68,6 @@ export default function ({ getService, getPageObjects }) { // so that we can override the existing visualization. await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_exists.json'), false); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.associateIndexPattern('logstash-*', 'logstash-*'); await PageObjects.settings.clickConfirmChanges(); @@ -88,7 +85,6 @@ export default function ({ getService, getPageObjects }) { // so that we can be prompted to override the existing visualization. await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_exists.json'), false); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.associateIndexPattern('logstash-*', 'logstash-*'); await PageObjects.settings.clickConfirmChanges(); @@ -102,13 +98,11 @@ export default function ({ getService, getPageObjects }) { it('should import saved objects linked to saved searches', async function () { await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_saved_search.json')); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.clickImportDone(); await PageObjects.settings.navigateTo(); await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_connected_to_saved_search.json')); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.clickImportDone(); await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); @@ -121,7 +115,6 @@ export default function ({ getService, getPageObjects }) { await PageObjects.settings.navigateTo(); await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_connected_to_saved_search.json')); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.clickImportDone(); await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); @@ -134,8 +127,6 @@ export default function ({ getService, getPageObjects }) { // First, import the saved search await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_saved_search.json')); - // Wait for all the saves to happen - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.clickImportDone(); // Second, we need to delete the index pattern @@ -149,8 +140,6 @@ export default function ({ getService, getPageObjects }) { await PageObjects.settings.navigateTo(); await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_connected_to_saved_search.json')); - // Wait for all the saves to happen - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.clickImportDone(); await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); @@ -163,7 +152,6 @@ export default function ({ getService, getPageObjects }) { // First, import the objects await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_with_index_patterns.json')); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.clickImportDone(); // Wait for all the saves to happen await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); @@ -183,7 +171,6 @@ export default function ({ getService, getPageObjects }) { // Then, import the objects await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_with_index_patterns.json')); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.clickImportDone(); // Wait for all the saves to happen await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); diff --git a/test/functional/apps/management/_mgmt_import_saved_objects.js b/test/functional/apps/management/_mgmt_import_saved_objects.js index e2bfd89f07544..914c989cf1c62 100644 --- a/test/functional/apps/management/_mgmt_import_saved_objects.js +++ b/test/functional/apps/management/_mgmt_import_saved_objects.js @@ -41,7 +41,6 @@ export default function ({ getService, getPageObjects }) { await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', 'mgmt_import_objects.json')); - await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.associateIndexPattern('4c3f3c30-ac94-11e8-a651-614b2788174a', 'logstash-*'); await PageObjects.settings.clickConfirmChanges(); await PageObjects.settings.clickImportDone(); diff --git a/test/functional/page_objects/settings_page.js b/test/functional/page_objects/settings_page.js index fa2be9eb9f28e..815f1a851b3f3 100644 --- a/test/functional/page_objects/settings_page.js +++ b/test/functional/page_objects/settings_page.js @@ -555,6 +555,9 @@ export function SettingsPageProvider({ getService, getPageObjects }) { } await testSubjects.click('importSavedObjectsImportBtn'); log.debug(`done importing the file`); + + // Wait for all the saves to happen + await PageObjects.header.waitUntilLoadingHasFinished(); } async clickImportDone() { From ef70258714ac2a16465679fa28350b02898c4b66 Mon Sep 17 00:00:00 2001 From: spalger Date: Fri, 22 Mar 2019 15:42:26 -0700 Subject: [PATCH 14/96] update kbn/pm dist --- packages/kbn-pm/dist/index.js | 11929 ++++++++++++-------------------- 1 file changed, 4321 insertions(+), 7608 deletions(-) diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 7ba71fb12f30e..5910f00408b17 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -17588,6 +17588,7 @@ function getProjectPaths(rootPath, options) { // In anyway, have a plugin declaring their own dependencies is the // correct and the expect behavior. projectPaths.push((0, _path.resolve)(rootPath, 'test/plugin_functional/plugins/*')); + projectPaths.push((0, _path.resolve)(rootPath, 'test/interpreter_functional/plugins/*')); if (!ossOnly) { projectPaths.push((0, _path.resolve)(rootPath, 'x-pack')); projectPaths.push((0, _path.resolve)(rootPath, 'x-pack/plugins/*')); @@ -31761,7 +31762,7 @@ Object.defineProperty(exports, 'buildProductionProjects', { } }); -var _prepare_project_dependencies = __webpack_require__(585); +var _prepare_project_dependencies = __webpack_require__(547); Object.defineProperty(exports, 'prepareExternalProjectDependencies', { enumerable: true, @@ -31946,8 +31947,8 @@ const EventEmitter = __webpack_require__(45); const path = __webpack_require__(16); const arrify = __webpack_require__(370); const globby = __webpack_require__(371); -const cpFile = __webpack_require__(577); -const CpyError = __webpack_require__(584); +const cpFile = __webpack_require__(539); +const CpyError = __webpack_require__(546); const preprocessSrcPath = (srcPath, options) => options.cwd ? path.resolve(options.cwd, srcPath) : srcPath; @@ -32069,8 +32070,8 @@ module.exports = function (val) { const arrayUnion = __webpack_require__(138); const glob = __webpack_require__(36); const fastGlob = __webpack_require__(372); -const dirGlob = __webpack_require__(573); -const gitignore = __webpack_require__(574); +const dirGlob = __webpack_require__(535); +const gitignore = __webpack_require__(536); const DEFAULT_FILTER = () => false; @@ -32219,10 +32220,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); var merge2 = __webpack_require__(374); var optionsManager = __webpack_require__(375); var taskManager = __webpack_require__(376); -var reader_async_1 = __webpack_require__(552); -var reader_stream_1 = __webpack_require__(571); -var reader_sync_1 = __webpack_require__(572); -var arrayUtils = __webpack_require__(568); +var reader_async_1 = __webpack_require__(514); +var reader_stream_1 = __webpack_require__(533); +var reader_sync_1 = __webpack_require__(534); +var arrayUtils = __webpack_require__(530); /** * Returns a set of works based on provided tasks and class of the reader. */ @@ -32948,10 +32949,10 @@ var extend = __webpack_require__(394); * Local dependencies */ -var compilers = __webpack_require__(520); -var parsers = __webpack_require__(548); -var cache = __webpack_require__(549); -var utils = __webpack_require__(550); +var compilers = __webpack_require__(488); +var parsers = __webpack_require__(510); +var cache = __webpack_require__(511); +var utils = __webpack_require__(512); var MAX_LENGTH = 1024 * 64; /** @@ -33828,16 +33829,15 @@ module.exports = micromatch; var toRegex = __webpack_require__(385); var unique = __webpack_require__(397); var extend = __webpack_require__(394); -var define = __webpack_require__(398); /** * Local dependencies */ -var compilers = __webpack_require__(405); -var parsers = __webpack_require__(420); +var compilers = __webpack_require__(398); +var parsers = __webpack_require__(413); var Braces = __webpack_require__(423); -var utils = __webpack_require__(406); +var utils = __webpack_require__(399); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -33940,8 +33940,9 @@ braces.create = function(pattern, options) { throw new TypeError('expected a string'); } - if (pattern.length >= MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); + var maxLength = (options && options.maxLength) || MAX_LENGTH; + if (pattern.length >= maxLength) { + throw new Error('expected pattern to be less than ' + maxLength + ' characters'); } function create() { @@ -33975,7 +33976,11 @@ braces.create = function(pattern, options) { arr = unique(arr); } - define(arr, 'result', result); + Object.defineProperty(arr, 'result', { + enumerable: false, + value: result + }); + return arr; } @@ -34002,8 +34007,9 @@ braces.makeRe = function(pattern, options) { throw new TypeError('expected a string'); } - if (pattern.length >= MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); + var maxLength = (options && options.maxLength) || MAX_LENGTH; + if (pattern.length >= maxLength) { + throw new Error('expected pattern to be less than ' + maxLength + ' characters'); } function makeRe() { @@ -35106,421 +35112,647 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * define-property - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ +var utils = __webpack_require__(399); -var isDescriptor = __webpack_require__(399); +module.exports = function(braces, options) { + braces.compiler -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } + /** + * bos + */ - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } + .set('bos', function() { + if (this.output) return; + this.ast.queue = isEscaped(this.ast) ? [this.ast.val] : []; + this.ast.count = 1; + }) - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } + /** + * Square brackets + */ - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; + .set('bracket', function(node) { + var close = node.close; + var open = !node.escaped ? '[' : '\\['; + var negated = node.negated; + var inner = node.inner; + inner = inner.replace(/\\(?=[\\\w]|$)/g, '\\\\'); + if (inner === ']-') { + inner = '\\]\\-'; + } -/***/ }), -/* 399 */ -/***/ (function(module, exports, __webpack_require__) { + if (negated && inner.indexOf('.') === -1) { + inner += '.'; + } + if (negated && inner.indexOf('/') === -1) { + inner += '/'; + } -"use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ + var val = open + negated + inner + close; + var queue = node.parent.queue; + var last = utils.arrayify(queue.pop()); + queue.push(utils.join(last, val)); + queue.push.apply(queue, []); + }) + /** + * Brace + */ -var typeOf = __webpack_require__(400); -var isAccessor = __webpack_require__(401); -var isData = __webpack_require__(403); + .set('brace', function(node) { + node.queue = isEscaped(node) ? [node.val] : []; + node.count = 1; + return this.mapVisit(node.nodes); + }) -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; - } - if ('get' in obj) { - return isAccessor(obj, key); - } - return isData(obj, key); -}; + /** + * Open + */ + .set('brace.open', function(node) { + node.parent.open = node.val; + }) -/***/ }), -/* 400 */ -/***/ (function(module, exports) { + /** + * Inner + */ -var toString = Object.prototype.toString; + .set('text', function(node) { + var queue = node.parent.queue; + var escaped = node.escaped; + var segs = [node.val]; -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; + if (node.optimize === false) { + options = utils.extend({}, options, {optimize: false}); + } - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } + if (node.multiplier > 1) { + node.parent.count *= node.multiplier; + } - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; + if (options.quantifiers === true && utils.isQuantifier(node.val)) { + escaped = true; - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; + } else if (node.val.length > 1) { + if (isType(node.parent, 'brace') && !isEscaped(node)) { + var expanded = utils.expand(node.val, options); + segs = expanded.segs; - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; + if (expanded.isOptimized) { + node.parent.isOptimized = true; + } - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; + // if nothing was expanded, we probably have a literal brace + if (!segs.length) { + var val = (expanded.val || node.val); + if (options.unescape !== false) { + // unescape unexpanded brace sequence/set separators + val = val.replace(/\\([,.])/g, '$1'); + // strip quotes + val = val.replace(/["'`]/g, ''); + } - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; + segs = [val]; + escaped = true; + } + } - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } + } else if (node.val === ',') { + if (options.expand) { + node.parent.queue.push(['']); + segs = ['']; + } else { + segs = ['|']; + } + } else { + escaped = true; + } - if (isGeneratorObj(val)) { - return 'generator'; - } + if (escaped && isType(node.parent, 'brace')) { + if (node.parent.nodes.length <= 4 && node.parent.count === 1) { + node.parent.escaped = true; + } else if (node.parent.length <= 3) { + node.parent.escaped = true; + } + } - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } + if (!hasQueue(node.parent)) { + node.parent.queue = segs; + return; + } + + var last = utils.arrayify(queue.pop()); + if (node.parent.count > 1 && options.expand) { + last = multiply(last, node.parent.count); + node.parent.count = 1; + } + + queue.push(utils.join(utils.flatten(last), segs.shift())); + queue.push.apply(queue, segs); + }) + + /** + * Close + */ + + .set('brace.close', function(node) { + var queue = node.parent.queue; + var prev = node.parent.parent; + var last = prev.queue.pop(); + var open = node.parent.open; + var close = node.val; + + if (open && close && isOptimized(node, options)) { + open = '('; + close = ')'; + } + + // if a close brace exists, and the previous segment is one character + // don't wrap the result in braces or parens + var ele = utils.last(queue); + if (node.parent.count > 1 && options.expand) { + ele = multiply(queue.pop(), node.parent.count); + node.parent.count = 1; + queue.push(ele); + } + + if (close && typeof ele === 'string' && ele.length === 1) { + open = ''; + close = ''; + } + + if ((isLiteralBrace(node, options) || noInner(node)) && !node.parent.hasEmpty) { + queue.push(utils.join(open, queue.pop() || '')); + queue = utils.flatten(utils.join(queue, close)); + } + + if (typeof last === 'undefined') { + prev.queue = [queue]; + } else { + prev.queue.push(utils.flatten(utils.join(last, queue))); + } + }) + + /** + * eos + */ + + .set('eos', function(node) { + if (this.input) return; + + if (options.optimize !== false) { + this.output = utils.last(utils.flatten(this.ast.queue)); + } else if (Array.isArray(utils.last(this.ast.queue))) { + this.output = utils.flatten(this.ast.queue.pop()); + } else { + this.output = utils.flatten(this.ast.queue); + } + + if (node.parent.count > 1 && options.expand) { + this.output = multiply(this.output, node.parent.count); + } + + this.output = utils.arrayify(this.output); + this.ast.queue = []; + }); - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); }; -function ctorName(val) { - return val.constructor ? val.constructor.name : null; -} +/** + * Multiply the segments in the current brace level + */ -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; +function multiply(queue, n, options) { + return utils.flatten(utils.repeat(utils.arrayify(queue), n)); } -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} +/** + * Return true if `node` is escaped + */ -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; +function isEscaped(node) { + return node.escaped === true; } -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} +/** + * Returns true if regex parens should be used for sets. If the parent `type` + * is not `brace`, then we're on a root node, which means we should never + * expand segments and open/close braces should be `{}` (since this indicates + * a brace is missing from the set) + */ -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; +function isOptimized(node, options) { + if (node.parent.isOptimized) return true; + return isType(node.parent, 'brace') + && !isEscaped(node.parent) + && options.expand !== true; } -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; +/** + * Returns true if the value in `node` should be wrapped in a literal brace. + * @return {Boolean} + */ + +function isLiteralBrace(node, options) { + return isEscaped(node.parent) || options.optimize !== false; } -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } +/** + * Returns true if the given `node` does not have an inner value. + * @return {Boolean} + */ + +function noInner(node, type) { + if (node.parent.queue.length === 1) { + return true; } - return false; + var nodes = node.parent.nodes; + return nodes.length === 3 + && isType(nodes[0], 'brace.open') + && !isType(nodes[1], 'text') + && isType(nodes[2], 'brace.close'); } /** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer + * Returns true if the given `node` is the given `type` + * @return {Boolean} */ -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; +function isType(node, type) { + return typeof node !== 'undefined' && node.type === type; +} + +/** + * Returns true if the given `node` has a non-empty queue. + * @return {Boolean} + */ + +function hasQueue(node) { + return Array.isArray(node.queue) && node.queue.length; } /***/ }), -/* 401 */ +/* 399 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * is-accessor-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. + + +var splitString = __webpack_require__(400); +var utils = module.exports; + +/** + * Module dependencies */ +utils.extend = __webpack_require__(394); +utils.flatten = __webpack_require__(406); +utils.isObject = __webpack_require__(404); +utils.fillRange = __webpack_require__(407); +utils.repeat = __webpack_require__(412); +utils.unique = __webpack_require__(397); +utils.define = function(obj, key, val) { + Object.defineProperty(obj, key, { + writable: true, + configurable: true, + enumerable: false, + value: val + }); +}; -var typeOf = __webpack_require__(402); +/** + * Returns true if the given string contains only empty brace sets. + */ -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' +utils.isEmptySets = function(str) { + return /^(?:\{,\})+$/.test(str); }; -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } +/** + * Returns true if the given string contains only empty brace sets. + */ - if (typeOf(obj) !== 'object') { - return false; +utils.isQuotedString = function(str) { + var open = str.charAt(0); + if (open === '\'' || open === '"' || open === '`') { + return str.slice(-1) === open; } + return false; +}; - if (has(obj, 'value') || has(obj, 'writable')) { - return false; - } +/** + * Create the key to use for memoization. The unique key is generated + * by iterating over the options and concatenating key-value pairs + * to the pattern string. + */ - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; +utils.createKey = function(pattern, options) { + var id = pattern; + if (typeof options === 'undefined') { + return id; } - - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; + var keys = Object.keys(options); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + id += ';' + key + '=' + String(options[key]); } + return id; +}; - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === accessor[key]) { - continue; - } +/** + * Normalize options + */ - if (typeof obj[key] !== 'undefined') { - return false; - } +utils.createOptions = function(options) { + var opts = utils.extend.apply(null, arguments); + if (typeof opts.expand === 'boolean') { + opts.optimize = !opts.expand; } - return true; -} - -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} + if (typeof opts.optimize === 'boolean') { + opts.expand = !opts.optimize; + } + if (opts.optimize === true) { + opts.makeRe = true; + } + return opts; +}; /** - * Expose `isAccessorDescriptor` + * Join patterns in `a` to patterns in `b` */ -module.exports = isAccessorDescriptor; +utils.join = function(a, b, options) { + options = options || {}; + a = utils.arrayify(a); + b = utils.arrayify(b); + if (!a.length) return b; + if (!b.length) return a; -/***/ }), -/* 402 */ -/***/ (function(module, exports) { + var len = a.length; + var idx = -1; + var arr = []; -var toString = Object.prototype.toString; + while (++idx < len) { + var val = a[idx]; + if (Array.isArray(val)) { + for (var i = 0; i < val.length; i++) { + val[i] = utils.join(val[i], b, options); + } + arr.push(val); + continue; + } -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; + for (var j = 0; j < b.length; j++) { + var bval = b[j]; - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; + if (Array.isArray(bval)) { + arr.push(utils.join(val, bval, options)); + } else { + arr.push(val + bval); + } + } } + return arr; +}; - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; +/** + * Split the given string on `,` if not escaped. + */ - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; +utils.split = function(str, options) { + var opts = utils.extend({sep: ','}, options); + if (typeof opts.keepQuotes !== 'boolean') { + opts.keepQuotes = true; + } + if (opts.unescape === false) { + opts.keepEscaping = true; + } + return splitString(str, opts, utils.escapeBrackets(opts)); +}; - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; +/** + * Expand ranges or sets in the given `pattern`. + * + * @param {String} `str` + * @param {Object} `options` + * @return {Object} + */ - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; +utils.expand = function(str, options) { + var opts = utils.extend({rangeLimit: 10000}, options); + var segs = utils.split(str, opts); + var tok = { segs: segs }; - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; + if (utils.isQuotedString(str)) { + return tok; } - if (isGeneratorObj(val)) { - return 'generator'; + if (opts.rangeLimit === true) { + opts.rangeLimit = 10000; } - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } + if (segs.length > 1) { + if (opts.optimize === false) { + tok.val = segs[0]; + return tok; + } - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; + tok.segs = utils.stringifyArray(tok.segs); + } else if (segs.length === 1) { + var arr = str.split('..'); -function ctorName(val) { - return val.constructor ? val.constructor.name : null; -} + if (arr.length === 1) { + tok.val = tok.segs[tok.segs.length - 1] || tok.val || str; + tok.segs = []; + return tok; + } -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} + if (arr.length === 2 && arr[0] === arr[1]) { + tok.escaped = true; + tok.val = arr[0]; + tok.segs = []; + return tok; + } -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} + if (arr.length > 1) { + if (opts.optimize !== false) { + opts.optimize = true; + delete opts.expand; + } -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} + if (opts.optimize !== true) { + var min = Math.min(arr[0], arr[1]); + var max = Math.max(arr[0], arr[1]); + var step = arr[2] || 1; -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} + if (opts.rangeLimit !== false && ((max - min) / step >= opts.rangeLimit)) { + throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); + } + } -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} + arr.push(opts); + tok.segs = utils.fillRange.apply(null, arr); -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} + if (!tok.segs.length) { + tok.escaped = true; + tok.val = str; + return tok; + } -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; + if (opts.optimize === true) { + tok.segs = utils.stringifyArray(tok.segs); + } + + if (tok.segs === '') { + tok.val = str; + } else { + tok.val = tok.segs[0]; + } + return tok; } + } else { + tok.val = str; } - return false; -} + return tok; +}; /** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer + * Ensure commas inside brackets and parens are not split. + * @param {Object} `tok` Token from the `split-string` module + * @return {undefined} */ -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); +utils.escapeBrackets = function(options) { + return function(tok) { + if (tok.escaped && tok.val === 'b') { + tok.val = '\\b'; + return; + } + + if (tok.val !== '(' && tok.val !== '[') return; + var opts = utils.extend({}, options); + var brackets = []; + var parens = []; + var stack = []; + var val = tok.val; + var str = tok.str; + var i = tok.idx - 1; + + while (++i < str.length) { + var ch = str[i]; + + if (ch === '\\') { + val += (opts.keepEscaping === false ? '' : ch) + str[++i]; + continue; + } + + if (ch === '(') { + parens.push(ch); + stack.push(ch); + } + + if (ch === '[') { + brackets.push(ch); + stack.push(ch); + } + + if (ch === ')') { + parens.pop(); + stack.pop(); + if (!stack.length) { + val += ch; + break; + } + } + + if (ch === ']') { + brackets.pop(); + stack.pop(); + if (!stack.length) { + val += ch; + break; + } + } + val += ch; + } + + tok.split = false; + tok.val = val.slice(1); + tok.idx = i; + }; +}; + +/** + * Returns true if the given string looks like a regex quantifier + * @return {Boolean} + */ + +utils.isQuantifier = function(str) { + return /^(?:[0-9]?,[0-9]|[0-9],)$/.test(str); +}; + +/** + * Cast `val` to an array. + * @param {*} `val` + */ + +utils.stringifyArray = function(arr) { + return [utils.arrayify(arr).join('|')]; +}; + +/** + * Cast `val` to an array. + * @param {*} `val` + */ + +utils.arrayify = function(arr) { + if (typeof arr === 'undefined') { + return []; } - return false; -} + if (typeof arr === 'string') { + return [arr]; + } + return arr; +}; + +/** + * Returns true if the given `str` is a non-empty string + * @return {Boolean} + */ + +utils.isString = function(str) { + return str != null && typeof str === 'string'; +}; + +/** + * Get the last element from `array` + * @param {Array} `array` + * @return {*} + */ + +utils.last = function(arr, n) { + return arr[arr.length - (n || 1)]; +}; + +utils.escapeRegex = function(str) { + return str.replace(/\\?([!^*?()[\]{}+?/])/g, '\\$1'); +}; /***/ }), -/* 403 */ +/* 400 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-data-descriptor + * split-string * * Copyright (c) 2015-2017, Jon Schlinkert. * Released under the MIT License. @@ -35528,2866 +35760,2648 @@ function isBuffer(val) { -var typeOf = __webpack_require__(404); +var extend = __webpack_require__(401); -module.exports = function isDataDescriptor(obj, prop) { - // data descriptor properties - var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' - }; +module.exports = function(str, options, fn) { + if (typeof str !== 'string') { + throw new TypeError('expected a string'); + } - if (typeOf(obj) !== 'object') { - return false; + if (typeof options === 'function') { + fn = options; + options = null; } - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; + // allow separator to be defined as a string + if (typeof options === 'string') { + options = { sep: options }; } - if (!('value' in obj) && !('writable' in obj)) { - return false; + var opts = extend({sep: '.'}, options); + var quotes = opts.quotes || ['"', "'", '`']; + var brackets; + + if (opts.brackets === true) { + brackets = { + '<': '>', + '(': ')', + '[': ']', + '{': '}' + }; + } else if (opts.brackets) { + brackets = opts.brackets; } - for (var key in obj) { - if (key === 'value') continue; + var tokens = []; + var stack = []; + var arr = ['']; + var sep = opts.sep; + var len = str.length; + var idx = -1; + var closeIdx; - if (!data.hasOwnProperty(key)) { - continue; + function expected() { + if (brackets && stack.length) { + return brackets[stack[stack.length - 1]]; } + } - if (typeOf(obj[key]) === data[key]) { + while (++idx < len) { + var ch = str[idx]; + var next = str[idx + 1]; + var tok = { val: ch, idx: idx, arr: arr, str: str }; + tokens.push(tok); + + if (ch === '\\') { + tok.val = keepEscaping(opts, str, idx) === true ? (ch + next) : next; + tok.escaped = true; + if (typeof fn === 'function') { + fn(tok); + } + arr[arr.length - 1] += tok.val; + idx++; continue; } - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -}; + if (brackets && brackets[ch]) { + stack.push(ch); + var e = expected(); + var i = idx + 1; + if (str.indexOf(e, i + 1) !== -1) { + while (stack.length && i < len) { + var s = str[++i]; + if (s === '\\') { + s++; + continue; + } -/***/ }), -/* 404 */ -/***/ (function(module, exports) { + if (quotes.indexOf(s) !== -1) { + i = getClosingQuote(str, s, i + 1); + continue; + } -var toString = Object.prototype.toString; + e = expected(); + if (stack.length && str.indexOf(e, i + 1) === -1) { + break; + } -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; + if (brackets[s]) { + stack.push(s); + continue; + } - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } + if (e === s) { + stack.pop(); + } + } + } - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; + closeIdx = i; + if (closeIdx === -1) { + arr[arr.length - 1] += ch; + continue; + } - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; + ch = str.slice(idx, closeIdx + 1); + tok.val = ch; + tok.idx = idx = closeIdx; + } - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; + if (quotes.indexOf(ch) !== -1) { + closeIdx = getClosingQuote(str, ch, idx + 1); + if (closeIdx === -1) { + arr[arr.length - 1] += ch; + continue; + } - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; + if (keepQuotes(ch, opts) === true) { + ch = str.slice(idx, closeIdx + 1); + } else { + ch = str.slice(idx + 1, closeIdx); + } - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; + tok.val = ch; + tok.idx = idx = closeIdx; + } - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } + if (typeof fn === 'function') { + fn(tok, tokens); + ch = tok.val; + idx = tok.idx; + } - if (isGeneratorObj(val)) { - return 'generator'; - } + if (tok.val === sep && tok.split !== false) { + arr.push(''); + continue; + } - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; + arr[arr.length - 1] += tok.val; } - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); + return arr; }; -function ctorName(val) { - return val.constructor ? val.constructor.name : null; +function getClosingQuote(str, ch, i, brackets) { + var idx = str.indexOf(ch, i); + if (str.charAt(idx - 1) === '\\') { + return getClosingQuote(str, ch, idx + 1); + } + return idx; } -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; +function keepQuotes(ch, opts) { + if (opts.keepDoubleQuotes === true && ch === '"') return true; + if (opts.keepSingleQuotes === true && ch === "'") return true; + return opts.keepQuotes; } -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); +function keepEscaping(opts, str, idx) { + if (typeof opts.keepEscaping === 'function') { + return opts.keepEscaping(str, idx); + } + return opts.keepEscaping === true || str[idx + 1] === '\\'; } -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} +/***/ }), +/* 401 */ +/***/ (function(module, exports, __webpack_require__) { -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} +"use strict"; -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; +var isExtendable = __webpack_require__(402); +var assignSymbols = __webpack_require__(405); + +module.exports = Object.assign || function(obj/*, objects*/) { + if (obj === null || typeof obj === 'undefined') { + throw new TypeError('Cannot convert undefined or null to object'); + } + if (!isObject(obj)) { + obj = {}; + } + for (var i = 1; i < arguments.length; i++) { + var val = arguments[i]; + if (isString(val)) { + val = toObject(val); } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; + if (isObject(val)) { + assign(obj, val); + assignSymbols(obj, val); } } - return false; + return obj; +}; + +function assign(a, b) { + for (var key in b) { + if (hasOwn(b, key)) { + a[key] = b[key]; + } + } +} + +function isString(val) { + return (val && typeof val === 'string'); +} + +function toObject(str) { + var obj = {}; + for (var i in str) { + obj[i] = str[i]; + } + return obj; +} + +function isObject(val) { + return (val && typeof val === 'object') || isExtendable(val); } /** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer + * Returns true if the given `key` is an own property of `obj`. */ -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} + +function isEnum(obj, key) { + return Object.prototype.propertyIsEnumerable.call(obj, key); } /***/ }), -/* 405 */ +/* 402 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +/*! + * is-extendable + * + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. + */ -var utils = __webpack_require__(406); - -module.exports = function(braces, options) { - braces.compiler - /** - * bos - */ +var isPlainObject = __webpack_require__(403); - .set('bos', function() { - if (this.output) return; - this.ast.queue = isEscaped(this.ast) ? [this.ast.val] : []; - this.ast.count = 1; - }) +module.exports = function isExtendable(val) { + return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); +}; - /** - * Square brackets - */ - .set('bracket', function(node) { - var close = node.close; - var open = !node.escaped ? '[' : '\\['; - var negated = node.negated; - var inner = node.inner; +/***/ }), +/* 403 */ +/***/ (function(module, exports, __webpack_require__) { - inner = inner.replace(/\\(?=[\\\w]|$)/g, '\\\\'); - if (inner === ']-') { - inner = '\\]\\-'; - } +"use strict"; +/*! + * is-plain-object + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ - if (negated && inner.indexOf('.') === -1) { - inner += '.'; - } - if (negated && inner.indexOf('/') === -1) { - inner += '/'; - } - var val = open + negated + inner + close; - var queue = node.parent.queue; - var last = utils.arrayify(queue.pop()); - queue.push(utils.join(last, val)); - queue.push.apply(queue, []); - }) +var isObject = __webpack_require__(404); - /** - * Brace - */ +function isObjectObject(o) { + return isObject(o) === true + && Object.prototype.toString.call(o) === '[object Object]'; +} - .set('brace', function(node) { - node.queue = isEscaped(node) ? [node.val] : []; - node.count = 1; - return this.mapVisit(node.nodes); - }) +module.exports = function isPlainObject(o) { + var ctor,prot; - /** - * Open - */ + if (isObjectObject(o) === false) return false; - .set('brace.open', function(node) { - node.parent.open = node.val; - }) + // If has modified constructor + ctor = o.constructor; + if (typeof ctor !== 'function') return false; - /** - * Inner - */ + // If has modified prototype + prot = ctor.prototype; + if (isObjectObject(prot) === false) return false; - .set('text', function(node) { - var queue = node.parent.queue; - var escaped = node.escaped; - var segs = [node.val]; + // If constructor does not have an Object-specific method + if (prot.hasOwnProperty('isPrototypeOf') === false) { + return false; + } - if (node.optimize === false) { - options = utils.extend({}, options, {optimize: false}); - } + // Most likely a plain Object + return true; +}; - if (node.multiplier > 1) { - node.parent.count *= node.multiplier; - } - if (options.quantifiers === true && utils.isQuantifier(node.val)) { - escaped = true; +/***/ }), +/* 404 */ +/***/ (function(module, exports, __webpack_require__) { - } else if (node.val.length > 1) { - if (isType(node.parent, 'brace') && !isEscaped(node)) { - var expanded = utils.expand(node.val, options); - segs = expanded.segs; +"use strict"; +/*! + * isobject + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ - if (expanded.isOptimized) { - node.parent.isOptimized = true; - } - // if nothing was expanded, we probably have a literal brace - if (!segs.length) { - var val = (expanded.val || node.val); - if (options.unescape !== false) { - // unescape unexpanded brace sequence/set separators - val = val.replace(/\\([,.])/g, '$1'); - // strip quotes - val = val.replace(/["'`]/g, ''); - } - segs = [val]; - escaped = true; - } - } +module.exports = function isObject(val) { + return val != null && typeof val === 'object' && Array.isArray(val) === false; +}; - } else if (node.val === ',') { - if (options.expand) { - node.parent.queue.push(['']); - segs = ['']; - } else { - segs = ['|']; - } - } else { - escaped = true; - } - if (escaped && isType(node.parent, 'brace')) { - if (node.parent.nodes.length <= 4 && node.parent.count === 1) { - node.parent.escaped = true; - } else if (node.parent.length <= 3) { - node.parent.escaped = true; - } - } +/***/ }), +/* 405 */ +/***/ (function(module, exports, __webpack_require__) { - if (!hasQueue(node.parent)) { - node.parent.queue = segs; - return; - } +"use strict"; +/*! + * assign-symbols + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ - var last = utils.arrayify(queue.pop()); - if (node.parent.count > 1 && options.expand) { - last = multiply(last, node.parent.count); - node.parent.count = 1; - } - queue.push(utils.join(utils.flatten(last), segs.shift())); - queue.push.apply(queue, segs); - }) - /** - * Close - */ +module.exports = function(receiver, objects) { + if (receiver === null || typeof receiver === 'undefined') { + throw new TypeError('expected first argument to be an object.'); + } - .set('brace.close', function(node) { - var queue = node.parent.queue; - var prev = node.parent.parent; - var last = prev.queue.pop(); - var open = node.parent.open; - var close = node.val; + if (typeof objects === 'undefined' || typeof Symbol === 'undefined') { + return receiver; + } - if (open && close && isOptimized(node, options)) { - open = '('; - close = ')'; - } + if (typeof Object.getOwnPropertySymbols !== 'function') { + return receiver; + } - // if a close brace exists, and the previous segment is one character - // don't wrap the result in braces or parens - var ele = utils.last(queue); - if (node.parent.count > 1 && options.expand) { - ele = multiply(queue.pop(), node.parent.count); - node.parent.count = 1; - queue.push(ele); - } + var isEnumerable = Object.prototype.propertyIsEnumerable; + var target = Object(receiver); + var len = arguments.length, i = 0; - if (close && typeof ele === 'string' && ele.length === 1) { - open = ''; - close = ''; - } + while (++i < len) { + var provider = Object(arguments[i]); + var names = Object.getOwnPropertySymbols(provider); - if ((isLiteralBrace(node, options) || noInner(node)) && !node.parent.hasEmpty) { - queue.push(utils.join(open, queue.pop() || '')); - queue = utils.flatten(utils.join(queue, close)); - } + for (var j = 0; j < names.length; j++) { + var key = names[j]; - if (typeof last === 'undefined') { - prev.queue = [queue]; - } else { - prev.queue.push(utils.flatten(utils.join(last, queue))); + if (isEnumerable.call(provider, key)) { + target[key] = provider[key]; } - }) + } + } + return target; +}; - /** - * eos - */ - .set('eos', function(node) { - if (this.input) return; +/***/ }), +/* 406 */ +/***/ (function(module, exports, __webpack_require__) { - if (options.optimize !== false) { - this.output = utils.last(utils.flatten(this.ast.queue)); - } else if (Array.isArray(utils.last(this.ast.queue))) { - this.output = utils.flatten(this.ast.queue.pop()); - } else { - this.output = utils.flatten(this.ast.queue); - } +"use strict"; +/*! + * arr-flatten + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ - if (node.parent.count > 1 && options.expand) { - this.output = multiply(this.output, node.parent.count); - } - this.output = utils.arrayify(this.output); - this.ast.queue = []; - }); +module.exports = function (arr) { + return flat(arr, []); }; -/** - * Multiply the segments in the current brace level - */ - -function multiply(queue, n, options) { - return utils.flatten(utils.repeat(utils.arrayify(queue), n)); +function flat(arr, res) { + var i = 0, cur; + var len = arr.length; + for (; i < len; i++) { + cur = arr[i]; + Array.isArray(cur) ? flat(cur, res) : res.push(cur); + } + return res; } -/** - * Return true if `node` is escaped - */ -function isEscaped(node) { - return node.escaped === true; -} +/***/ }), +/* 407 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Returns true if regex parens should be used for sets. If the parent `type` - * is not `brace`, then we're on a root node, which means we should never - * expand segments and open/close braces should be `{}` (since this indicates - * a brace is missing from the set) +"use strict"; +/*! + * fill-range + * + * Copyright (c) 2014-2015, 2017, Jon Schlinkert. + * Released under the MIT License. */ -function isOptimized(node, options) { - if (node.parent.isOptimized) return true; - return isType(node.parent, 'brace') - && !isEscaped(node.parent) - && options.expand !== true; -} -/** - * Returns true if the value in `node` should be wrapped in a literal brace. - * @return {Boolean} - */ -function isLiteralBrace(node, options) { - return isEscaped(node.parent) || options.optimize !== false; -} +var util = __webpack_require__(29); +var isNumber = __webpack_require__(408); +var extend = __webpack_require__(394); +var repeat = __webpack_require__(410); +var toRegex = __webpack_require__(411); /** - * Returns true if the given `node` does not have an inner value. - * @return {Boolean} + * Return a range of numbers or letters. + * + * @param {String} `start` Start of the range + * @param {String} `stop` End of the range + * @param {String} `step` Increment or decrement to use. + * @param {Function} `fn` Custom function to modify each element in the range. + * @return {Array} */ -function noInner(node, type) { - if (node.parent.queue.length === 1) { - return true; +function fillRange(start, stop, step, options) { + if (typeof start === 'undefined') { + return []; } - var nodes = node.parent.nodes; - return nodes.length === 3 - && isType(nodes[0], 'brace.open') - && !isType(nodes[1], 'text') - && isType(nodes[2], 'brace.close'); -} -/** - * Returns true if the given `node` is the given `type` - * @return {Boolean} - */ + if (typeof stop === 'undefined' || start === stop) { + // special case, for handling negative zero + var isString = typeof start === 'string'; + if (isNumber(start) && !toNumber(start)) { + return [isString ? '0' : 0]; + } + return [start]; + } -function isType(node, type) { - return typeof node !== 'undefined' && node.type === type; -} + if (typeof step !== 'number' && typeof step !== 'string') { + options = step; + step = undefined; + } -/** - * Returns true if the given `node` has a non-empty queue. - * @return {Boolean} - */ + if (typeof options === 'function') { + options = { transform: options }; + } -function hasQueue(node) { - return Array.isArray(node.queue) && node.queue.length; -} + var opts = extend({step: step}, options); + if (opts.step && !isValidNumber(opts.step)) { + if (opts.strictRanges === true) { + throw new TypeError('expected options.step to be a number'); + } + return []; + } + opts.isNumber = isValidNumber(start) && isValidNumber(stop); + if (!opts.isNumber && !isValid(start, stop)) { + if (opts.strictRanges === true) { + throw new RangeError('invalid range arguments: ' + util.inspect([start, stop])); + } + return []; + } -/***/ }), -/* 406 */ -/***/ (function(module, exports, __webpack_require__) { + opts.isPadded = isPadded(start) || isPadded(stop); + opts.toString = opts.stringify + || typeof opts.step === 'string' + || typeof start === 'string' + || typeof stop === 'string' + || !opts.isNumber; -"use strict"; + if (opts.isPadded) { + opts.maxLength = Math.max(String(start).length, String(stop).length); + } + // support legacy minimatch/fill-range options + if (typeof opts.optimize === 'boolean') opts.toRegex = opts.optimize; + if (typeof opts.makeRe === 'boolean') opts.toRegex = opts.makeRe; + return expand(start, stop, opts); +} -var splitString = __webpack_require__(407); -var utils = module.exports; +function expand(start, stop, options) { + var a = options.isNumber ? toNumber(start) : start.charCodeAt(0); + var b = options.isNumber ? toNumber(stop) : stop.charCodeAt(0); -/** - * Module dependencies - */ + var step = Math.abs(toNumber(options.step)) || 1; + if (options.toRegex && step === 1) { + return toRange(a, b, start, stop, options); + } -utils.define = __webpack_require__(398); -utils.extend = __webpack_require__(394); -utils.flatten = __webpack_require__(413); -utils.isObject = __webpack_require__(411); -utils.fillRange = __webpack_require__(414); -utils.repeat = __webpack_require__(419); -utils.unique = __webpack_require__(397); + var zero = {greater: [], lesser: []}; + var asc = a < b; + var arr = new Array(Math.round((asc ? b - a : a - b) / step)); + var idx = 0; -/** - * Returns true if the given string contains only empty brace sets. - */ - -utils.isEmptySets = function(str) { - return /^(?:\{,\})+$/.test(str); -}; - -/** - * Returns true if the given string contains only empty brace sets. - */ - -utils.isQuotedString = function(str) { - var open = str.charAt(0); - if (open === '\'' || open === '"' || open === '`') { - return str.slice(-1) === open; - } - return false; -}; - -/** - * Create the key to use for memoization. The unique key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ - -utils.createKey = function(pattern, options) { - var id = pattern; - if (typeof options === 'undefined') { - return id; - } - var keys = Object.keys(options); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - id += ';' + key + '=' + String(options[key]); - } - return id; -}; - -/** - * Normalize options - */ - -utils.createOptions = function(options) { - var opts = utils.extend.apply(null, arguments); - if (typeof opts.expand === 'boolean') { - opts.optimize = !opts.expand; - } - if (typeof opts.optimize === 'boolean') { - opts.expand = !opts.optimize; - } - if (opts.optimize === true) { - opts.makeRe = true; - } - return opts; -}; - -/** - * Join patterns in `a` to patterns in `b` - */ - -utils.join = function(a, b, options) { - options = options || {}; - a = utils.arrayify(a); - b = utils.arrayify(b); - - if (!a.length) return b; - if (!b.length) return a; + while (asc ? a <= b : a >= b) { + var val = options.isNumber ? a : String.fromCharCode(a); + if (options.toRegex && (val >= 0 || !options.isNumber)) { + zero.greater.push(val); + } else { + zero.lesser.push(Math.abs(val)); + } - var len = a.length; - var idx = -1; - var arr = []; + if (options.isPadded) { + val = zeros(val, options); + } - while (++idx < len) { - var val = a[idx]; - if (Array.isArray(val)) { - for (var i = 0; i < val.length; i++) { - val[i] = utils.join(val[i], b, options); - } - arr.push(val); - continue; + if (options.toString) { + val = String(val); } - for (var j = 0; j < b.length; j++) { - var bval = b[j]; + if (typeof options.transform === 'function') { + arr[idx++] = options.transform(val, a, b, step, idx, arr, options); + } else { + arr[idx++] = val; + } - if (Array.isArray(bval)) { - arr.push(utils.join(val, bval, options)); - } else { - arr.push(val + bval); - } + if (asc) { + a += step; + } else { + a -= step; } } - return arr; -}; - -/** - * Split the given string on `,` if not escaped. - */ -utils.split = function(str, options) { - var opts = utils.extend({sep: ','}, options); - if (typeof opts.keepQuotes !== 'boolean') { - opts.keepQuotes = true; + if (options.toRegex === true) { + return toSequence(arr, zero, options); } - if (opts.unescape === false) { - opts.keepEscaping = true; + return arr; +} + +function toRange(a, b, start, stop, options) { + if (options.isPadded) { + return toRegex(start, stop, options); } - return splitString(str, opts, utils.escapeBrackets(opts)); -}; -/** - * Expand ranges or sets in the given `pattern`. - * - * @param {String} `str` - * @param {Object} `options` - * @return {Object} - */ + if (options.isNumber) { + return toRegex(Math.min(a, b), Math.max(a, b), options); + } -utils.expand = function(str, options) { - var opts = utils.extend({rangeLimit: 10000}, options); - var segs = utils.split(str, opts); - var tok = { segs: segs }; + var start = String.fromCharCode(Math.min(a, b)); + var stop = String.fromCharCode(Math.max(a, b)); + return '[' + start + '-' + stop + ']'; +} - if (utils.isQuotedString(str)) { - return tok; +function toSequence(arr, zeros, options) { + var greater = '', lesser = ''; + if (zeros.greater.length) { + greater = zeros.greater.join('|'); + } + if (zeros.lesser.length) { + lesser = '-(' + zeros.lesser.join('|') + ')'; } + var res = greater && lesser + ? greater + '|' + lesser + : greater || lesser; - if (opts.rangeLimit === true) { - opts.rangeLimit = 10000; + if (options.capture) { + return '(' + res + ')'; } + return res; +} - if (segs.length > 1) { - if (opts.optimize === false) { - tok.val = segs[0]; - return tok; +function zeros(val, options) { + if (options.isPadded) { + var str = String(val); + var len = str.length; + var dash = ''; + if (str.charAt(0) === '-') { + dash = '-'; + str = str.slice(1); } + var diff = options.maxLength - len; + var pad = repeat('0', diff); + val = (dash + pad + str); + } + if (options.stringify) { + return String(val); + } + return val; +} - tok.segs = utils.stringifyArray(tok.segs); - } else if (segs.length === 1) { - var arr = str.split('..'); - - if (arr.length === 1) { - tok.val = tok.segs[tok.segs.length - 1] || tok.val || str; - tok.segs = []; - return tok; - } +function toNumber(val) { + return Number(val) || 0; +} - if (arr.length === 2 && arr[0] === arr[1]) { - tok.escaped = true; - tok.val = arr[0]; - tok.segs = []; - return tok; - } +function isPadded(str) { + return /^-?0\d/.test(str); +} - if (arr.length > 1) { - if (opts.optimize !== false) { - opts.optimize = true; - delete opts.expand; - } +function isValid(min, max) { + return (isValidNumber(min) || isValidLetter(min)) + && (isValidNumber(max) || isValidLetter(max)); +} - if (opts.optimize !== true) { - var min = Math.min(arr[0], arr[1]); - var max = Math.max(arr[0], arr[1]); - var step = arr[2] || 1; +function isValidLetter(ch) { + return typeof ch === 'string' && ch.length === 1 && /^\w+$/.test(ch); +} - if (opts.rangeLimit !== false && ((max - min) / step >= opts.rangeLimit)) { - throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); - } - } +function isValidNumber(n) { + return isNumber(n) && !/\./.test(n); +} - arr.push(opts); - tok.segs = utils.fillRange.apply(null, arr); +/** + * Expose `fillRange` + * @type {Function} + */ - if (!tok.segs.length) { - tok.escaped = true; - tok.val = str; - return tok; - } +module.exports = fillRange; - if (opts.optimize === true) { - tok.segs = utils.stringifyArray(tok.segs); - } - if (tok.segs === '') { - tok.val = str; - } else { - tok.val = tok.segs[0]; - } - return tok; - } - } else { - tok.val = str; - } - return tok; -}; +/***/ }), +/* 408 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Ensure commas inside brackets and parens are not split. - * @param {Object} `tok` Token from the `split-string` module - * @return {undefined} +"use strict"; +/*! + * is-number + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. */ -utils.escapeBrackets = function(options) { - return function(tok) { - if (tok.escaped && tok.val === 'b') { - tok.val = '\\b'; - return; - } - if (tok.val !== '(' && tok.val !== '[') return; - var opts = utils.extend({}, options); - var brackets = []; - var parens = []; - var stack = []; - var val = tok.val; - var str = tok.str; - var i = tok.idx - 1; - while (++i < str.length) { - var ch = str[i]; +var typeOf = __webpack_require__(409); - if (ch === '\\') { - val += (opts.keepEscaping === false ? '' : ch) + str[++i]; - continue; - } +module.exports = function isNumber(num) { + var type = typeOf(num); - if (ch === '(') { - parens.push(ch); - stack.push(ch); - } + if (type === 'string') { + if (!num.trim()) return false; + } else if (type !== 'number') { + return false; + } - if (ch === '[') { - brackets.push(ch); - stack.push(ch); - } + return (num - num + 1) >= 0; +}; - if (ch === ')') { - parens.pop(); - stack.pop(); - if (!stack.length) { - val += ch; - break; - } - } - if (ch === ']') { - brackets.pop(); - stack.pop(); - if (!stack.length) { - val += ch; - break; - } - } - val += ch; - } +/***/ }), +/* 409 */ +/***/ (function(module, exports, __webpack_require__) { - tok.split = false; - tok.val = val.slice(1); - tok.idx = i; - }; -}; +var isBuffer = __webpack_require__(391); +var toString = Object.prototype.toString; /** - * Returns true if the given string looks like a regex quantifier - * @return {Boolean} + * Get the native `typeof` a value. + * + * @param {*} `val` + * @return {*} Native javascript type */ -utils.isQuantifier = function(str) { - return /^(?:[0-9]?,[0-9]|[0-9],)$/.test(str); -}; - -/** - * Cast `val` to an array. - * @param {*} `val` - */ +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; + } -utils.stringifyArray = function(arr) { - return [utils.arrayify(arr).join('|')]; -}; + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } -/** - * Cast `val` to an array. - * @param {*} `val` - */ + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } -utils.arrayify = function(arr) { - if (typeof arr === 'undefined') { - return []; + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; } - if (typeof arr === 'string') { - return [arr]; + if (val instanceof Date) { + return 'date'; } - return arr; -}; -/** - * Returns true if the given `str` is a non-empty string - * @return {Boolean} - */ + // other objects + var type = toString.call(val); -utils.isString = function(str) { - return str != null && typeof str === 'string'; -}; + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; + } -/** - * Get the last element from `array` - * @param {Array} `array` - * @return {*} - */ + // buffer + if (isBuffer(val)) { + return 'buffer'; + } -utils.last = function(arr, n) { - return arr[arr.length - (n || 1)]; -}; + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } -utils.escapeRegex = function(str) { - return str.replace(/\\?([!^*?()\[\]{}+?/])/g, '\\$1'); + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } + + // must be a plain object + return 'object'; }; /***/ }), -/* 407 */ +/* 410 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * split-string + * repeat-string * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. */ -var extend = __webpack_require__(408); - -module.exports = function(str, options, fn) { - if (typeof str !== 'string') { - throw new TypeError('expected a string'); - } +/** + * Results cache + */ - if (typeof options === 'function') { - fn = options; - options = null; - } +var res = ''; +var cache; - // allow separator to be defined as a string - if (typeof options === 'string') { - options = { sep: options }; - } +/** + * Expose `repeat` + */ - var opts = extend({sep: '.'}, options); - var quotes = opts.quotes || ['"', "'", '`']; - var brackets; +module.exports = repeat; - if (opts.brackets === true) { - brackets = { - '<': '>', - '(': ')', - '[': ']', - '{': '}' - }; - } else if (opts.brackets) { - brackets = opts.brackets; +/** + * Repeat the given `string` the specified `number` + * of times. + * + * **Example:** + * + * ```js + * var repeat = require('repeat-string'); + * repeat('A', 5); + * //=> AAAAA + * ``` + * + * @param {String} `string` The string to repeat + * @param {Number} `number` The number of times to repeat the string + * @return {String} Repeated string + * @api public + */ + +function repeat(str, num) { + if (typeof str !== 'string') { + throw new TypeError('expected a string'); } - var tokens = []; - var stack = []; - var arr = ['']; - var sep = opts.sep; - var len = str.length; - var idx = -1; - var closeIdx; + // cover common, quick use cases + if (num === 1) return str; + if (num === 2) return str + str; - function expected() { - if (brackets && stack.length) { - return brackets[stack[stack.length - 1]]; + var max = str.length * num; + if (cache !== str || typeof cache === 'undefined') { + cache = str; + res = ''; + } else if (res.length >= max) { + return res.substr(0, max); + } + + while (max > res.length && num > 1) { + if (num & 1) { + res += str; } + + num >>= 1; + str += str; } - while (++idx < len) { - var ch = str[idx]; - var next = str[idx + 1]; - var tok = { val: ch, idx: idx, arr: arr, str: str }; - tokens.push(tok); + res += str; + res = res.substr(0, max); + return res; +} - if (ch === '\\') { - tok.val = keepEscaping(opts, str, idx) === true ? (ch + next) : next; - tok.escaped = true; - if (typeof fn === 'function') { - fn(tok); - } - arr[arr.length - 1] += tok.val; - idx++; - continue; - } - if (brackets && brackets[ch]) { - stack.push(ch); - var e = expected(); - var i = idx + 1; +/***/ }), +/* 411 */ +/***/ (function(module, exports, __webpack_require__) { - if (str.indexOf(e, i + 1) !== -1) { - while (stack.length && i < len) { - var s = str[++i]; - if (s === '\\') { - s++; - continue; - } +"use strict"; +/*! + * to-regex-range + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ - if (quotes.indexOf(s) !== -1) { - i = getClosingQuote(str, s, i + 1); - continue; - } - e = expected(); - if (stack.length && str.indexOf(e, i + 1) === -1) { - break; - } - if (brackets[s]) { - stack.push(s); - continue; - } +var repeat = __webpack_require__(410); +var isNumber = __webpack_require__(408); +var cache = {}; - if (e === s) { - stack.pop(); - } - } - } +function toRegexRange(min, max, options) { + if (isNumber(min) === false) { + throw new RangeError('toRegexRange: first argument is invalid.'); + } - closeIdx = i; - if (closeIdx === -1) { - arr[arr.length - 1] += ch; - continue; - } + if (typeof max === 'undefined' || min === max) { + return String(min); + } - ch = str.slice(idx, closeIdx + 1); - tok.val = ch; - tok.idx = idx = closeIdx; - } + if (isNumber(max) === false) { + throw new RangeError('toRegexRange: second argument is invalid.'); + } - if (quotes.indexOf(ch) !== -1) { - closeIdx = getClosingQuote(str, ch, idx + 1); - if (closeIdx === -1) { - arr[arr.length - 1] += ch; - continue; - } + options = options || {}; + var relax = String(options.relaxZeros); + var shorthand = String(options.shorthand); + var capture = String(options.capture); + var key = min + ':' + max + '=' + relax + shorthand + capture; + if (cache.hasOwnProperty(key)) { + return cache[key].result; + } - if (keepQuotes(ch, opts) === true) { - ch = str.slice(idx, closeIdx + 1); - } else { - ch = str.slice(idx + 1, closeIdx); - } + var a = Math.min(min, max); + var b = Math.max(min, max); - tok.val = ch; - tok.idx = idx = closeIdx; + if (Math.abs(a - b) === 1) { + var result = min + '|' + max; + if (options.capture) { + return '(' + result + ')'; } + return result; + } - if (typeof fn === 'function') { - fn(tok, tokens); - ch = tok.val; - idx = tok.idx; - } + var isPadded = padding(min) || padding(max); + var positives = []; + var negatives = []; - if (tok.val === sep && tok.split !== false) { - arr.push(''); - continue; - } + var tok = {min: min, max: max, a: a, b: b}; + if (isPadded) { + tok.isPadded = isPadded; + tok.maxLen = String(tok.max).length; + } - arr[arr.length - 1] += tok.val; + if (a < 0) { + var newMin = b < 0 ? Math.abs(b) : 1; + var newMax = Math.abs(a); + negatives = splitToPatterns(newMin, newMax, tok, options); + a = tok.a = 0; } - return arr; -}; + if (b >= 0) { + positives = splitToPatterns(a, b, tok, options); + } -function getClosingQuote(str, ch, i, brackets) { - var idx = str.indexOf(ch, i); - if (str.charAt(idx - 1) === '\\') { - return getClosingQuote(str, ch, idx + 1); + tok.negatives = negatives; + tok.positives = positives; + tok.result = siftPatterns(negatives, positives, options); + + if (options.capture && (positives.length + negatives.length) > 1) { + tok.result = '(' + tok.result + ')'; } - return idx; + + cache[key] = tok; + return tok.result; } -function keepQuotes(ch, opts) { - if (opts.keepDoubleQuotes === true && ch === '"') return true; - if (opts.keepSingleQuotes === true && ch === "'") return true; - return opts.keepQuotes; +function siftPatterns(neg, pos, options) { + var onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; + var onlyPositive = filterPatterns(pos, neg, '', false, options) || []; + var intersected = filterPatterns(neg, pos, '-?', true, options) || []; + var subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); + return subpatterns.join('|'); } -function keepEscaping(opts, str, idx) { - if (typeof opts.keepEscaping === 'function') { - return opts.keepEscaping(str, idx); +function splitToRanges(min, max) { + min = Number(min); + max = Number(max); + + var nines = 1; + var stops = [max]; + var stop = +countNines(min, nines); + + while (min <= stop && stop <= max) { + stops = push(stops, stop); + nines += 1; + stop = +countNines(min, nines); } - return opts.keepEscaping === true || str[idx + 1] === '\\'; + + var zeros = 1; + stop = countZeros(max + 1, zeros) - 1; + + while (min < stop && stop <= max) { + stops = push(stops, stop); + zeros += 1; + stop = countZeros(max + 1, zeros) - 1; + } + + stops.sort(compare); + return stops; } +/** + * Convert a range to a regex pattern + * @param {Number} `start` + * @param {Number} `stop` + * @return {String} + */ + +function rangeToPattern(start, stop, options) { + if (start === stop) { + return {pattern: String(start), digits: []}; + } -/***/ }), -/* 408 */ -/***/ (function(module, exports, __webpack_require__) { + var zipped = zip(String(start), String(stop)); + var len = zipped.length, i = -1; -"use strict"; + var pattern = ''; + var digits = 0; + while (++i < len) { + var numbers = zipped[i]; + var startDigit = numbers[0]; + var stopDigit = numbers[1]; -var isExtendable = __webpack_require__(409); -var assignSymbols = __webpack_require__(412); + if (startDigit === stopDigit) { + pattern += startDigit; -module.exports = Object.assign || function(obj/*, objects*/) { - if (obj === null || typeof obj === 'undefined') { - throw new TypeError('Cannot convert undefined or null to object'); - } - if (!isObject(obj)) { - obj = {}; - } - for (var i = 1; i < arguments.length; i++) { - var val = arguments[i]; - if (isString(val)) { - val = toObject(val); - } - if (isObject(val)) { - assign(obj, val); - assignSymbols(obj, val); - } - } - return obj; -}; + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit); -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; + } else { + digits += 1; } } -} - -function isString(val) { - return (val && typeof val === 'string'); -} -function toObject(str) { - var obj = {}; - for (var i in str) { - obj[i] = str[i]; + if (digits) { + pattern += options.shorthand ? '\\d' : '[0-9]'; } - return obj; -} -function isObject(val) { - return (val && typeof val === 'object') || isExtendable(val); + return { pattern: pattern, digits: [digits] }; } -/** - * Returns true if the given `key` is an own property of `obj`. - */ +function splitToPatterns(min, max, tok, options) { + var ranges = splitToRanges(min, max); + var len = ranges.length; + var idx = -1; -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} + var tokens = []; + var start = min; + var prev; -function isEnum(obj, key) { - return Object.prototype.propertyIsEnumerable.call(obj, key); -} + while (++idx < len) { + var range = ranges[idx]; + var obj = rangeToPattern(start, range, options); + var zeros = ''; + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.digits.length > 1) { + prev.digits.pop(); + } + prev.digits.push(obj.digits[0]); + prev.string = prev.pattern + toQuantifier(prev.digits); + start = range + 1; + continue; + } -/***/ }), -/* 409 */ -/***/ (function(module, exports, __webpack_require__) { + if (tok.isPadded) { + zeros = padZeros(range, tok); + } -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ + obj.string = zeros + obj.pattern + toQuantifier(obj.digits); + tokens.push(obj); + start = range + 1; + prev = obj; + } + return tokens; +} +function filterPatterns(arr, comparison, prefix, intersection, options) { + var res = []; -var isPlainObject = __webpack_require__(410); + for (var i = 0; i < arr.length; i++) { + var tok = arr[i]; + var ele = tok.string; -module.exports = function isExtendable(val) { - return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); -}; + if (options.relaxZeros !== false) { + if (prefix === '-' && ele.charAt(0) === '0') { + if (ele.charAt(1) === '{') { + ele = '0*' + ele.replace(/^0\{\d+\}/, ''); + } else { + ele = '0*' + ele.slice(1); + } + } + } + if (!intersection && !contains(comparison, 'string', ele)) { + res.push(prefix + ele); + } -/***/ }), -/* 410 */ -/***/ (function(module, exports, __webpack_require__) { + if (intersection && contains(comparison, 'string', ele)) { + res.push(prefix + ele); + } + } + return res; +} -"use strict"; -/*! - * is-plain-object - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. +/** + * Zip strings (`for in` can be used on string characters) */ +function zip(a, b) { + var arr = []; + for (var ch in a) arr.push([a[ch], b[ch]]); + return arr; +} +function compare(a, b) { + return a > b ? 1 : b > a ? -1 : 0; +} -var isObject = __webpack_require__(411); +function push(arr, ele) { + if (arr.indexOf(ele) === -1) arr.push(ele); + return arr; +} -function isObjectObject(o) { - return isObject(o) === true - && Object.prototype.toString.call(o) === '[object Object]'; +function contains(arr, key, val) { + for (var i = 0; i < arr.length; i++) { + if (arr[i][key] === val) { + return true; + } + } + return false; } -module.exports = function isPlainObject(o) { - var ctor,prot; +function countNines(min, len) { + return String(min).slice(0, -len) + repeat('9', len); +} - if (isObjectObject(o) === false) return false; +function countZeros(integer, zeros) { + return integer - (integer % Math.pow(10, zeros)); +} - // If has modified constructor - ctor = o.constructor; - if (typeof ctor !== 'function') return false; +function toQuantifier(digits) { + var start = digits[0]; + var stop = digits[1] ? (',' + digits[1]) : ''; + if (!stop && (!start || start === 1)) { + return ''; + } + return '{' + start + stop + '}'; +} - // If has modified prototype - prot = ctor.prototype; - if (isObjectObject(prot) === false) return false; +function toCharacterClass(a, b) { + return '[' + a + ((b - a === 1) ? '' : '-') + b + ']'; +} - // If constructor does not have an Object-specific method - if (prot.hasOwnProperty('isPrototypeOf') === false) { - return false; +function padding(str) { + return /^-?(0+)\d/.exec(str); +} + +function padZeros(val, tok) { + if (tok.isPadded) { + var diff = Math.abs(tok.maxLen - String(val).length); + switch (diff) { + case 0: + return ''; + case 1: + return '0'; + default: { + return '0{' + diff + '}'; + } + } } + return val; +} - // Most likely a plain Object - return true; -}; +/** + * Expose `toRegexRange` + */ + +module.exports = toRegexRange; /***/ }), -/* 411 */ +/* 412 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * isobject + * repeat-element * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. + * Copyright (c) 2015 Jon Schlinkert. + * Licensed under the MIT license. */ -module.exports = function isObject(val) { - return val != null && typeof val === 'object' && Array.isArray(val) === false; +module.exports = function repeat(ele, num) { + var arr = new Array(num); + + for (var i = 0; i < num; i++) { + arr[i] = ele; + } + + return arr; }; /***/ }), -/* 412 */ +/* 413 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * assign-symbols - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ +var Node = __webpack_require__(414); +var utils = __webpack_require__(399); -module.exports = function(receiver, objects) { - if (receiver === null || typeof receiver === 'undefined') { - throw new TypeError('expected first argument to be an object.'); - } +/** + * Braces parsers + */ - if (typeof objects === 'undefined' || typeof Symbol === 'undefined') { - return receiver; - } +module.exports = function(braces, options) { + braces.parser + .set('bos', function() { + if (!this.parsed) { + this.ast = this.nodes[0] = new Node(this.ast); + } + }) - if (typeof Object.getOwnPropertySymbols !== 'function') { - return receiver; - } + /** + * Character parsers + */ - var isEnumerable = Object.prototype.propertyIsEnumerable; - var target = Object(receiver); - var len = arguments.length, i = 0; + .set('escape', function() { + var pos = this.position(); + var m = this.match(/^(?:\\(.)|\$\{)/); + if (!m) return; - while (++i < len) { - var provider = Object(arguments[i]); - var names = Object.getOwnPropertySymbols(provider); + var prev = this.prev(); + var last = utils.last(prev.nodes); - for (var j = 0; j < names.length; j++) { - var key = names[j]; + var node = pos(new Node({ + type: 'text', + multiplier: 1, + val: m[0] + })); - if (isEnumerable.call(provider, key)) { - target[key] = provider[key]; + if (node.val === '\\\\') { + return node; } - } - } - return target; -}; + if (node.val === '${') { + var str = this.input; + var idx = -1; + var ch; -/***/ }), -/* 413 */ -/***/ (function(module, exports, __webpack_require__) { + while ((ch = str[++idx])) { + this.consume(1); + node.val += ch; + if (ch === '\\') { + node.val += str[++idx]; + continue; + } + if (ch === '}') { + break; + } + } + } -"use strict"; -/*! - * arr-flatten - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ + if (this.options.unescape !== false) { + node.val = node.val.replace(/\\([{}])/g, '$1'); + } + if (last.val === '"' && this.input.charAt(0) === '"') { + last.val = node.val; + this.consume(1); + return; + } + return concatNodes.call(this, pos, node, prev, options); + }) -module.exports = function (arr) { - return flat(arr, []); -}; + /** + * Brackets: "[...]" (basic, this is overridden by + * other parsers in more advanced implementations) + */ -function flat(arr, res) { - var i = 0, cur; - var len = arr.length; - for (; i < len; i++) { - cur = arr[i]; - Array.isArray(cur) ? flat(cur, res) : res.push(cur); - } - return res; -} + .set('bracket', function() { + var isInside = this.isInside('brace'); + var pos = this.position(); + var m = this.match(/^(?:\[([!^]?)([^\]]{2,}|\]-)(\]|[^*+?]+)|\[)/); + if (!m) return; + var prev = this.prev(); + var val = m[0]; + var negated = m[1] ? '^' : ''; + var inner = m[2] || ''; + var close = m[3] || ''; -/***/ }), -/* 414 */ -/***/ (function(module, exports, __webpack_require__) { + if (isInside && prev.type === 'brace') { + prev.text = prev.text || ''; + prev.text += val; + } -"use strict"; -/*! - * fill-range - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ + var esc = this.input.slice(0, 2); + if (inner === '' && esc === '\\]') { + inner += esc; + this.consume(2); + var str = this.input; + var idx = -1; + var ch; + while ((ch = str[++idx])) { + this.consume(1); + if (ch === ']') { + close = ch; + break; + } + inner += ch; + } + } -var util = __webpack_require__(29); -var isNumber = __webpack_require__(415); -var extend = __webpack_require__(394); -var repeat = __webpack_require__(417); -var toRegex = __webpack_require__(418); + return pos(new Node({ + type: 'bracket', + val: val, + escaped: close !== ']', + negated: negated, + inner: inner, + close: close + })); + }) -/** - * Return a range of numbers or letters. - * - * @param {String} `start` Start of the range - * @param {String} `stop` End of the range - * @param {String} `step` Increment or decrement to use. - * @param {Function} `fn` Custom function to modify each element in the range. - * @return {Array} - */ + /** + * Empty braces (we capture these early to + * speed up processing in the compiler) + */ -function fillRange(start, stop, step, options) { - if (typeof start === 'undefined') { - return []; - } + .set('multiplier', function() { + var isInside = this.isInside('brace'); + var pos = this.position(); + var m = this.match(/^\{((?:,|\{,+\})+)\}/); + if (!m) return; - if (typeof stop === 'undefined' || start === stop) { - // special case, for handling negative zero - var isString = typeof start === 'string'; - if (isNumber(start) && !toNumber(start)) { - return [isString ? '0' : 0]; - } - return [start]; - } + this.multiplier = true; + var prev = this.prev(); + var val = m[0]; - if (typeof step !== 'number' && typeof step !== 'string') { - options = step; - step = undefined; - } + if (isInside && prev.type === 'brace') { + prev.text = prev.text || ''; + prev.text += val; + } - if (typeof options === 'function') { - options = { transform: options }; - } + var node = pos(new Node({ + type: 'text', + multiplier: 1, + match: m, + val: val + })); - var opts = extend({step: step}, options); - if (opts.step && !isValidNumber(opts.step)) { - if (opts.strictRanges === true) { - throw new TypeError('expected options.step to be a number'); - } - return []; - } + return concatNodes.call(this, pos, node, prev, options); + }) - opts.isNumber = isValidNumber(start) && isValidNumber(stop); - if (!opts.isNumber && !isValid(start, stop)) { - if (opts.strictRanges === true) { - throw new RangeError('invalid range arguments: ' + util.inspect([start, stop])); - } - return []; - } + /** + * Open + */ - opts.isPadded = isPadded(start) || isPadded(stop); - opts.toString = opts.stringify - || typeof opts.step === 'string' - || typeof start === 'string' - || typeof stop === 'string' - || !opts.isNumber; + .set('brace.open', function() { + var pos = this.position(); + var m = this.match(/^\{(?!(?:[^\\}]?|,+)\})/); + if (!m) return; - if (opts.isPadded) { - opts.maxLength = Math.max(String(start).length, String(stop).length); - } + var prev = this.prev(); + var last = utils.last(prev.nodes); - // support legacy minimatch/fill-range options - if (typeof opts.optimize === 'boolean') opts.toRegex = opts.optimize; - if (typeof opts.makeRe === 'boolean') opts.toRegex = opts.makeRe; - return expand(start, stop, opts); -} + // if the last parsed character was an extglob character + // we need to _not optimize_ the brace pattern because + // it might be mistaken for an extglob by a downstream parser + if (last && last.val && isExtglobChar(last.val.slice(-1))) { + last.optimize = false; + } -function expand(start, stop, options) { - var a = options.isNumber ? toNumber(start) : start.charCodeAt(0); - var b = options.isNumber ? toNumber(stop) : stop.charCodeAt(0); + var open = pos(new Node({ + type: 'brace.open', + val: m[0] + })); - var step = Math.abs(toNumber(options.step)) || 1; - if (options.toRegex && step === 1) { - return toRange(a, b, start, stop, options); - } + var node = pos(new Node({ + type: 'brace', + nodes: [] + })); - var zero = {greater: [], lesser: []}; - var asc = a < b; - var arr = new Array(Math.round((asc ? b - a : a - b) / step)); - var idx = 0; + node.push(open); + prev.push(node); + this.push('brace', node); + }) - while (asc ? a <= b : a >= b) { - var val = options.isNumber ? a : String.fromCharCode(a); - if (options.toRegex && (val >= 0 || !options.isNumber)) { - zero.greater.push(val); - } else { - zero.lesser.push(Math.abs(val)); - } + /** + * Close + */ - if (options.isPadded) { - val = zeros(val, options); - } + .set('brace.close', function() { + var pos = this.position(); + var m = this.match(/^\}/); + if (!m || !m[0]) return; - if (options.toString) { - val = String(val); - } + var brace = this.pop('brace'); + var node = pos(new Node({ + type: 'brace.close', + val: m[0] + })); - if (typeof options.transform === 'function') { - arr[idx++] = options.transform(val, a, b, step, idx, arr, options); - } else { - arr[idx++] = val; - } + if (!this.isType(brace, 'brace')) { + if (this.options.strict) { + throw new Error('missing opening "{"'); + } + node.type = 'text'; + node.multiplier = 0; + node.escaped = true; + return node; + } - if (asc) { - a += step; - } else { - a -= step; - } - } + var prev = this.prev(); + var last = utils.last(prev.nodes); + if (last.text) { + var lastNode = utils.last(last.nodes); + if (lastNode.val === ')' && /[!@*?+]\(/.test(last.text)) { + var open = last.nodes[0]; + var text = last.nodes[1]; + if (open.type === 'brace.open' && text && text.type === 'text') { + text.optimize = false; + } + } + } - if (options.toRegex === true) { - return toSequence(arr, zero, options); - } - return arr; -} + if (brace.nodes.length > 2) { + var first = brace.nodes[1]; + if (first.type === 'text' && first.val === ',') { + brace.nodes.splice(1, 1); + brace.nodes.push(first); + } + } -function toRange(a, b, start, stop, options) { - if (options.isPadded) { - return toRegex(start, stop, options); - } + brace.push(node); + }) - if (options.isNumber) { - return toRegex(Math.min(a, b), Math.max(a, b), options); - } + /** + * Capture boundary characters + */ - var start = String.fromCharCode(Math.min(a, b)); - var stop = String.fromCharCode(Math.max(a, b)); - return '[' + start + '-' + stop + ']'; -} + .set('boundary', function() { + var pos = this.position(); + var m = this.match(/^[$^](?!\{)/); + if (!m) return; + return pos(new Node({ + type: 'text', + val: m[0] + })); + }) -function toSequence(arr, zeros, options) { - var greater = '', lesser = ''; - if (zeros.greater.length) { - greater = zeros.greater.join('|'); - } - if (zeros.lesser.length) { - lesser = '-(' + zeros.lesser.join('|') + ')'; - } - var res = greater && lesser - ? greater + '|' + lesser - : greater || lesser; + /** + * One or zero, non-comma characters wrapped in braces + */ - if (options.capture) { - return '(' + res + ')'; - } - return res; -} + .set('nobrace', function() { + var isInside = this.isInside('brace'); + var pos = this.position(); + var m = this.match(/^\{[^,]?\}/); + if (!m) return; -function zeros(val, options) { - if (options.isPadded) { - var str = String(val); - var len = str.length; - var dash = ''; - if (str.charAt(0) === '-') { - dash = '-'; - str = str.slice(1); - } - var diff = options.maxLength - len; - var pad = repeat('0', diff); - val = (dash + pad + str); - } - if (options.stringify) { - return String(val); - } - return val; -} + var prev = this.prev(); + var val = m[0]; -function toNumber(val) { - return Number(val) || 0; -} + if (isInside && prev.type === 'brace') { + prev.text = prev.text || ''; + prev.text += val; + } -function isPadded(str) { - return /^-?0\d/.test(str); -} + return pos(new Node({ + type: 'text', + multiplier: 0, + val: val + })); + }) -function isValid(min, max) { - return (isValidNumber(min) || isValidLetter(min)) - && (isValidNumber(max) || isValidLetter(max)); -} + /** + * Text + */ -function isValidLetter(ch) { - return typeof ch === 'string' && ch.length === 1 && /^\w+$/.test(ch); -} + .set('text', function() { + var isInside = this.isInside('brace'); + var pos = this.position(); + var m = this.match(/^((?!\\)[^${}[\]])+/); + if (!m) return; -function isValidNumber(n) { - return isNumber(n) && !/\./.test(n); -} + var prev = this.prev(); + var val = m[0]; + + if (isInside && prev.type === 'brace') { + prev.text = prev.text || ''; + prev.text += val; + } + + var node = pos(new Node({ + type: 'text', + multiplier: 1, + val: val + })); + + return concatNodes.call(this, pos, node, prev, options); + }); +}; /** - * Expose `fillRange` - * @type {Function} + * Returns true if the character is an extglob character. */ -module.exports = fillRange; +function isExtglobChar(ch) { + return ch === '!' || ch === '@' || ch === '*' || ch === '?' || ch === '+'; +} + +/** + * Combine text nodes, and calculate empty sets (`{,,}`) + * @param {Function} `pos` Function to calculate node position + * @param {Object} `node` AST node + * @return {Object} + */ +function concatNodes(pos, node, parent, options) { + node.orig = node.val; + var prev = this.prev(); + var last = utils.last(prev.nodes); + var isEscaped = false; -/***/ }), -/* 415 */ -/***/ (function(module, exports, __webpack_require__) { + if (node.val.length > 1) { + var a = node.val.charAt(0); + var b = node.val.slice(-1); -"use strict"; -/*! - * is-number - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ + isEscaped = (a === '"' && b === '"') + || (a === "'" && b === "'") + || (a === '`' && b === '`'); + } + if (isEscaped && options.unescape !== false) { + node.val = node.val.slice(1, node.val.length - 1); + node.escaped = true; + } + if (node.match) { + var match = node.match[1]; + if (!match || match.indexOf('}') === -1) { + match = node.match[0]; + } -var typeOf = __webpack_require__(416); + // replace each set with a single "," + var val = match.replace(/\{/g, ',').replace(/\}/g, ''); + node.multiplier *= val.length; + node.val = ''; + } -module.exports = function isNumber(num) { - var type = typeOf(num); + var simpleText = last.type === 'text' + && last.multiplier === 1 + && node.multiplier === 1 + && node.val; - if (type === 'string') { - if (!num.trim()) return false; - } else if (type !== 'number') { - return false; + if (simpleText) { + last.val += node.val; + return; } - return (num - num + 1) >= 0; -}; + prev.push(node); +} /***/ }), -/* 416 */ +/* 414 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; +"use strict"; + + +var isObject = __webpack_require__(404); +var define = __webpack_require__(415); +var utils = __webpack_require__(422); +var ownNames; /** - * Get the native `typeof` a value. + * Create a new AST `Node` with the given `val` and `type`. * - * @param {*} `val` - * @return {*} Native javascript type + * ```js + * var node = new Node('*', 'Star'); + * var node = new Node({type: 'star', val: '*'}); + * ``` + * @name Node + * @param {String|Object} `val` Pass a matched substring, or an object to merge onto the node. + * @param {String} `type` The node type to use when `val` is a string. + * @return {Object} node instance + * @api public */ -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; +function Node(val, type, parent) { + if (typeof type !== 'string') { + parent = type; + type = null; } - // other objects - var type = toString.call(val); + define(this, 'parent', parent); + define(this, 'isNode', true); + define(this, 'expect', null); - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; + if (typeof type !== 'string' && isObject(val)) { + lazyKeys(); + var keys = Object.keys(val); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (ownNames.indexOf(key) === -1) { + this[key] = val[key]; + } + } + } else { + this.type = type; + this.val = val; } +} - // buffer - if (isBuffer(val)) { - return 'buffer'; - } +/** + * Returns true if the given value is a node. + * + * ```js + * var Node = require('snapdragon-node'); + * var node = new Node({type: 'foo'}); + * console.log(Node.isNode(node)); //=> true + * console.log(Node.isNode({})); //=> false + * ``` + * @param {Object} `node` + * @returns {Boolean} + * @api public + */ - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } +Node.isNode = function(node) { + return utils.isNode(node); +}; - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } +/** + * Define a non-enumberable property on the node instance. + * Useful for adding properties that shouldn't be extended + * or visible during debugging. + * + * ```js + * var node = new Node(); + * node.define('foo', 'something non-enumerable'); + * ``` + * @param {String} `name` + * @param {any} `val` + * @return {Object} returns the node instance + * @api public + */ - // must be a plain object - return 'object'; +Node.prototype.define = function(name, val) { + define(this, name, val); + return this; }; +/** + * Returns true if `node.val` is an empty string, or `node.nodes` does + * not contain any non-empty text nodes. + * + * ```js + * var node = new Node({type: 'text'}); + * node.isEmpty(); //=> true + * node.val = 'foo'; + * node.isEmpty(); //=> false + * ``` + * @param {Function} `fn` (optional) Filter function that is called on `node` and/or child nodes. `isEmpty` will return false immediately when the filter function returns false on any nodes. + * @return {Boolean} + * @api public + */ -/***/ }), -/* 417 */ -/***/ (function(module, exports, __webpack_require__) { +Node.prototype.isEmpty = function(fn) { + return utils.isEmpty(this, fn); +}; -"use strict"; -/*! - * repeat-string +/** + * Given node `foo` and node `bar`, push node `bar` onto `foo.nodes`, and + * set `foo` as `bar.parent`. * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * foo.push(bar); + * ``` + * @param {Object} `node` + * @return {Number} Returns the length of `node.nodes` + * @api public */ +Node.prototype.push = function(node) { + assert(Node.isNode(node), 'expected node to be an instance of Node'); + define(node, 'parent', this); + this.nodes = this.nodes || []; + return this.nodes.push(node); +}; /** - * Results cache + * Given node `foo` and node `bar`, unshift node `bar` onto `foo.nodes`, and + * set `foo` as `bar.parent`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * foo.unshift(bar); + * ``` + * @param {Object} `node` + * @return {Number} Returns the length of `node.nodes` + * @api public */ -var res = ''; -var cache; +Node.prototype.unshift = function(node) { + assert(Node.isNode(node), 'expected node to be an instance of Node'); + define(node, 'parent', this); + + this.nodes = this.nodes || []; + return this.nodes.unshift(node); +}; /** - * Expose `repeat` + * Pop a node from `node.nodes`. + * + * ```js + * var node = new Node({type: 'foo'}); + * node.push(new Node({type: 'a'})); + * node.push(new Node({type: 'b'})); + * node.push(new Node({type: 'c'})); + * node.push(new Node({type: 'd'})); + * console.log(node.nodes.length); + * //=> 4 + * node.pop(); + * console.log(node.nodes.length); + * //=> 3 + * ``` + * @return {Number} Returns the popped `node` + * @api public */ -module.exports = repeat; +Node.prototype.pop = function() { + return this.nodes && this.nodes.pop(); +}; /** - * Repeat the given `string` the specified `number` - * of times. - * - * **Example:** + * Shift a node from `node.nodes`. * * ```js - * var repeat = require('repeat-string'); - * repeat('A', 5); - * //=> AAAAA + * var node = new Node({type: 'foo'}); + * node.push(new Node({type: 'a'})); + * node.push(new Node({type: 'b'})); + * node.push(new Node({type: 'c'})); + * node.push(new Node({type: 'd'})); + * console.log(node.nodes.length); + * //=> 4 + * node.shift(); + * console.log(node.nodes.length); + * //=> 3 * ``` - * - * @param {String} `string` The string to repeat - * @param {Number} `number` The number of times to repeat the string - * @return {String} Repeated string + * @return {Object} Returns the shifted `node` * @api public */ -function repeat(str, num) { - if (typeof str !== 'string') { - throw new TypeError('expected a string'); - } +Node.prototype.shift = function() { + return this.nodes && this.nodes.shift(); +}; - // cover common, quick use cases - if (num === 1) return str; - if (num === 2) return str + str; +/** + * Remove `node` from `node.nodes`. + * + * ```js + * node.remove(childNode); + * ``` + * @param {Object} `node` + * @return {Object} Returns the removed node. + * @api public + */ - var max = str.length * num; - if (cache !== str || typeof cache === 'undefined') { - cache = str; - res = ''; - } else if (res.length >= max) { - return res.substr(0, max); +Node.prototype.remove = function(node) { + assert(Node.isNode(node), 'expected node to be an instance of Node'); + this.nodes = this.nodes || []; + var idx = node.index; + if (idx !== -1) { + node.index = -1; + return this.nodes.splice(idx, 1); } + return null; +}; - while (max > res.length && num > 1) { - if (num & 1) { - res += str; - } - - num >>= 1; - str += str; - } +/** + * Get the first child node from `node.nodes` that matches the given `type`. + * If `type` is a number, the child node at that index is returned. + * + * ```js + * var child = node.find(1); //<= index of the node to get + * var child = node.find('foo'); //<= node.type of a child node + * var child = node.find(/^(foo|bar)$/); //<= regex to match node.type + * var child = node.find(['foo', 'bar']); //<= array of node.type(s) + * ``` + * @param {String} `type` + * @return {Object} Returns a child node or undefined. + * @api public + */ - res += str; - res = res.substr(0, max); - return res; -} +Node.prototype.find = function(type) { + return utils.findNode(this.nodes, type); +}; +/** + * Return true if the node is the given `type`. + * + * ```js + * var node = new Node({type: 'bar'}); + * cosole.log(node.isType('foo')); // false + * cosole.log(node.isType(/^(foo|bar)$/)); // true + * cosole.log(node.isType(['foo', 'bar'])); // true + * ``` + * @param {String} `type` + * @return {Boolean} + * @api public + */ -/***/ }), -/* 418 */ -/***/ (function(module, exports, __webpack_require__) { +Node.prototype.isType = function(type) { + return utils.isType(this, type); +}; -"use strict"; -/*! - * to-regex-range +/** + * Return true if the `node.nodes` has the given `type`. * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * foo.push(bar); + * + * cosole.log(foo.hasType('qux')); // false + * cosole.log(foo.hasType(/^(qux|bar)$/)); // true + * cosole.log(foo.hasType(['qux', 'bar'])); // true + * ``` + * @param {String} `type` + * @return {Boolean} + * @api public */ +Node.prototype.hasType = function(type) { + return utils.hasType(this, type); +}; +/** + * Get the siblings array, or `null` if it doesn't exist. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * foo.push(bar); + * foo.push(baz); + * + * console.log(bar.siblings.length) // 2 + * console.log(baz.siblings.length) // 2 + * ``` + * @return {Array} + * @api public + */ -var repeat = __webpack_require__(417); -var isNumber = __webpack_require__(415); -var cache = {}; - -function toRegexRange(min, max, options) { - if (isNumber(min) === false) { - throw new RangeError('toRegexRange: first argument is invalid.'); +Object.defineProperty(Node.prototype, 'siblings', { + set: function() { + throw new Error('node.siblings is a getter and cannot be defined'); + }, + get: function() { + return this.parent ? this.parent.nodes : null; } +}); - if (typeof max === 'undefined' || min === max) { - return String(min); - } +/** + * Get the node's current index from `node.parent.nodes`. + * This should always be correct, even when the parent adds nodes. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * var qux = new Node({type: 'qux'}); + * foo.push(bar); + * foo.push(baz); + * foo.unshift(qux); + * + * console.log(bar.index) // 1 + * console.log(baz.index) // 2 + * console.log(qux.index) // 0 + * ``` + * @return {Number} + * @api public + */ - if (isNumber(max) === false) { - throw new RangeError('toRegexRange: second argument is invalid.'); +Object.defineProperty(Node.prototype, 'index', { + set: function(index) { + define(this, 'idx', index); + }, + get: function() { + if (!Array.isArray(this.siblings)) { + return -1; + } + var tok = this.idx !== -1 ? this.siblings[this.idx] : null; + if (tok !== this) { + this.idx = this.siblings.indexOf(this); + } + return this.idx; } +}); - options = options || {}; - var relax = String(options.relaxZeros); - var shorthand = String(options.shorthand); - var capture = String(options.capture); - var key = min + ':' + max + '=' + relax + shorthand + capture; - if (cache.hasOwnProperty(key)) { - return cache[key].result; +/** + * Get the previous node from the siblings array or `null`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * foo.push(bar); + * foo.push(baz); + * + * console.log(baz.prev.type) // 'bar' + * ``` + * @return {Object} + * @api public + */ + +Object.defineProperty(Node.prototype, 'prev', { + set: function() { + throw new Error('node.prev is a getter and cannot be defined'); + }, + get: function() { + if (Array.isArray(this.siblings)) { + return this.siblings[this.index - 1] || this.parent.prev; + } + return null; } +}); - var a = Math.min(min, max); - var b = Math.max(min, max); +/** + * Get the siblings array, or `null` if it doesn't exist. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * foo.push(bar); + * foo.push(baz); + * + * console.log(bar.siblings.length) // 2 + * console.log(baz.siblings.length) // 2 + * ``` + * @return {Object} + * @api public + */ - if (Math.abs(a - b) === 1) { - var result = min + '|' + max; - if (options.capture) { - return '(' + result + ')'; +Object.defineProperty(Node.prototype, 'next', { + set: function() { + throw new Error('node.next is a getter and cannot be defined'); + }, + get: function() { + if (Array.isArray(this.siblings)) { + return this.siblings[this.index + 1] || this.parent.next; } - return result; + return null; } +}); - var isPadded = padding(min) || padding(max); - var positives = []; - var negatives = []; +/** + * Get the first node from `node.nodes`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * var qux = new Node({type: 'qux'}); + * foo.push(bar); + * foo.push(baz); + * foo.push(qux); + * + * console.log(foo.first.type) // 'bar' + * ``` + * @return {Object} The first node, or undefiend + * @api public + */ - var tok = {min: min, max: max, a: a, b: b}; - if (isPadded) { - tok.isPadded = isPadded; - tok.maxLen = String(tok.max).length; +Object.defineProperty(Node.prototype, 'first', { + get: function() { + return this.nodes ? this.nodes[0] : null; } +}); - if (a < 0) { - var newMin = b < 0 ? Math.abs(b) : 1; - var newMax = Math.abs(a); - negatives = splitToPatterns(newMin, newMax, tok, options); - a = tok.a = 0; - } +/** + * Get the last node from `node.nodes`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * var qux = new Node({type: 'qux'}); + * foo.push(bar); + * foo.push(baz); + * foo.push(qux); + * + * console.log(foo.last.type) // 'qux' + * ``` + * @return {Object} The last node, or undefiend + * @api public + */ - if (b >= 0) { - positives = splitToPatterns(a, b, tok, options); +Object.defineProperty(Node.prototype, 'last', { + get: function() { + return this.nodes ? utils.last(this.nodes) : null; } +}); - tok.negatives = negatives; - tok.positives = positives; - tok.result = siftPatterns(negatives, positives, options); +/** + * Get the last node from `node.nodes`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * var qux = new Node({type: 'qux'}); + * foo.push(bar); + * foo.push(baz); + * foo.push(qux); + * + * console.log(foo.last.type) // 'qux' + * ``` + * @return {Object} The last node, or undefiend + * @api public + */ - if (options.capture && (positives.length + negatives.length) > 1) { - tok.result = '(' + tok.result + ')'; +Object.defineProperty(Node.prototype, 'scope', { + get: function() { + if (this.isScope !== true) { + return this.parent ? this.parent.scope : this; + } + return this; } +}); - cache[key] = tok; - return tok.result; -} +/** + * Get own property names from Node prototype, but only the + * first time `Node` is instantiated + */ -function siftPatterns(neg, pos, options) { - var onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; - var onlyPositive = filterPatterns(pos, neg, '', false, options) || []; - var intersected = filterPatterns(neg, pos, '-?', true, options) || []; - var subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); - return subpatterns.join('|'); +function lazyKeys() { + if (!ownNames) { + ownNames = Object.getOwnPropertyNames(Node.prototype); + } } -function splitToRanges(min, max) { - min = Number(min); - max = Number(max); +/** + * Simplified assertion. Throws an error is `val` is falsey. + */ - var nines = 1; - var stops = [max]; - var stop = +countNines(min, nines); +function assert(val, message) { + if (!val) throw new Error(message); +} - while (min <= stop && stop <= max) { - stops = push(stops, stop); - nines += 1; - stop = +countNines(min, nines); - } +/** + * Expose `Node` + */ - var zeros = 1; - stop = countZeros(max + 1, zeros) - 1; +exports = module.exports = Node; - while (min < stop && stop <= max) { - stops = push(stops, stop); - zeros += 1; - stop = countZeros(max + 1, zeros) - 1; - } - stops.sort(compare); - return stops; -} +/***/ }), +/* 415 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Convert a range to a regex pattern - * @param {Number} `start` - * @param {Number} `stop` - * @return {String} +"use strict"; +/*! + * define-property + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. */ -function rangeToPattern(start, stop, options) { - if (start === stop) { - return {pattern: String(start), digits: []}; + + +var isDescriptor = __webpack_require__(416); + +module.exports = function defineProperty(obj, prop, val) { + if (typeof obj !== 'object' && typeof obj !== 'function') { + throw new TypeError('expected an object or function.'); } - var zipped = zip(String(start), String(stop)); - var len = zipped.length, i = -1; + if (typeof prop !== 'string') { + throw new TypeError('expected `prop` to be a string.'); + } - var pattern = ''; - var digits = 0; + if (isDescriptor(val) && ('set' in val || 'get' in val)) { + return Object.defineProperty(obj, prop, val); + } - while (++i < len) { - var numbers = zipped[i]; - var startDigit = numbers[0]; - var stopDigit = numbers[1]; + return Object.defineProperty(obj, prop, { + configurable: true, + enumerable: false, + writable: true, + value: val + }); +}; - if (startDigit === stopDigit) { - pattern += startDigit; - } else if (startDigit !== '0' || stopDigit !== '9') { - pattern += toCharacterClass(startDigit, stopDigit); +/***/ }), +/* 416 */ +/***/ (function(module, exports, __webpack_require__) { - } else { - digits += 1; - } - } +"use strict"; +/*! + * is-descriptor + * + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. + */ - if (digits) { - pattern += options.shorthand ? '\\d' : '[0-9]'; - } - return { pattern: pattern, digits: [digits] }; -} -function splitToPatterns(min, max, tok, options) { - var ranges = splitToRanges(min, max); - var len = ranges.length; - var idx = -1; +var typeOf = __webpack_require__(417); +var isAccessor = __webpack_require__(418); +var isData = __webpack_require__(420); - var tokens = []; - var start = min; - var prev; +module.exports = function isDescriptor(obj, key) { + if (typeOf(obj) !== 'object') { + return false; + } + if ('get' in obj) { + return isAccessor(obj, key); + } + return isData(obj, key); +}; - while (++idx < len) { - var range = ranges[idx]; - var obj = rangeToPattern(start, range, options); - var zeros = ''; - if (!tok.isPadded && prev && prev.pattern === obj.pattern) { - if (prev.digits.length > 1) { - prev.digits.pop(); - } - prev.digits.push(obj.digits[0]); - prev.string = prev.pattern + toQuantifier(prev.digits); - start = range + 1; - continue; - } +/***/ }), +/* 417 */ +/***/ (function(module, exports) { - if (tok.isPadded) { - zeros = padZeros(range, tok); - } +var toString = Object.prototype.toString; - obj.string = zeros + obj.pattern + toQuantifier(obj.digits); - tokens.push(obj); - start = range + 1; - prev = obj; +module.exports = function kindOf(val) { + if (val === void 0) return 'undefined'; + if (val === null) return 'null'; + + var type = typeof val; + if (type === 'boolean') return 'boolean'; + if (type === 'string') return 'string'; + if (type === 'number') return 'number'; + if (type === 'symbol') return 'symbol'; + if (type === 'function') { + return isGeneratorFn(val) ? 'generatorfunction' : 'function'; } - return tokens; -} + if (isArray(val)) return 'array'; + if (isBuffer(val)) return 'buffer'; + if (isArguments(val)) return 'arguments'; + if (isDate(val)) return 'date'; + if (isError(val)) return 'error'; + if (isRegexp(val)) return 'regexp'; -function filterPatterns(arr, comparison, prefix, intersection, options) { - var res = []; + switch (ctorName(val)) { + case 'Symbol': return 'symbol'; + case 'Promise': return 'promise'; - for (var i = 0; i < arr.length; i++) { - var tok = arr[i]; - var ele = tok.string; + // Set, Map, WeakSet, WeakMap + case 'WeakMap': return 'weakmap'; + case 'WeakSet': return 'weakset'; + case 'Map': return 'map'; + case 'Set': return 'set'; - if (options.relaxZeros !== false) { - if (prefix === '-' && ele.charAt(0) === '0') { - if (ele.charAt(1) === '{') { - ele = '0*' + ele.replace(/^0\{\d+\}/, ''); - } else { - ele = '0*' + ele.slice(1); - } - } - } + // 8-bit typed arrays + case 'Int8Array': return 'int8array'; + case 'Uint8Array': return 'uint8array'; + case 'Uint8ClampedArray': return 'uint8clampedarray'; - if (!intersection && !contains(comparison, 'string', ele)) { - res.push(prefix + ele); - } + // 16-bit typed arrays + case 'Int16Array': return 'int16array'; + case 'Uint16Array': return 'uint16array'; - if (intersection && contains(comparison, 'string', ele)) { - res.push(prefix + ele); - } + // 32-bit typed arrays + case 'Int32Array': return 'int32array'; + case 'Uint32Array': return 'uint32array'; + case 'Float32Array': return 'float32array'; + case 'Float64Array': return 'float64array'; } - return res; -} -/** - * Zip strings (`for in` can be used on string characters) - */ + if (isGeneratorObj(val)) { + return 'generator'; + } -function zip(a, b) { - var arr = []; - for (var ch in a) arr.push([a[ch], b[ch]]); - return arr; -} + // Non-plain objects + type = toString.call(val); + switch (type) { + case '[object Object]': return 'object'; + // iterators + case '[object Map Iterator]': return 'mapiterator'; + case '[object Set Iterator]': return 'setiterator'; + case '[object String Iterator]': return 'stringiterator'; + case '[object Array Iterator]': return 'arrayiterator'; + } -function compare(a, b) { - return a > b ? 1 : b > a ? -1 : 0; -} + // other + return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); +}; -function push(arr, ele) { - if (arr.indexOf(ele) === -1) arr.push(ele); - return arr; +function ctorName(val) { + return val.constructor ? val.constructor.name : null; } -function contains(arr, key, val) { - for (var i = 0; i < arr.length; i++) { - if (arr[i][key] === val) { - return true; - } - } - return false; +function isArray(val) { + if (Array.isArray) return Array.isArray(val); + return val instanceof Array; } -function countNines(min, len) { - return String(min).slice(0, -len) + repeat('9', len); +function isError(val) { + return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); } -function countZeros(integer, zeros) { - return integer - (integer % Math.pow(10, zeros)); +function isDate(val) { + if (val instanceof Date) return true; + return typeof val.toDateString === 'function' + && typeof val.getDate === 'function' + && typeof val.setDate === 'function'; } -function toQuantifier(digits) { - var start = digits[0]; - var stop = digits[1] ? (',' + digits[1]) : ''; - if (!stop && (!start || start === 1)) { - return ''; - } - return '{' + start + stop + '}'; +function isRegexp(val) { + if (val instanceof RegExp) return true; + return typeof val.flags === 'string' + && typeof val.ignoreCase === 'boolean' + && typeof val.multiline === 'boolean' + && typeof val.global === 'boolean'; } -function toCharacterClass(a, b) { - return '[' + a + ((b - a === 1) ? '' : '-') + b + ']'; +function isGeneratorFn(name, val) { + return ctorName(name) === 'GeneratorFunction'; } -function padding(str) { - return /^-?(0+)\d/.exec(str); +function isGeneratorObj(val) { + return typeof val.throw === 'function' + && typeof val.return === 'function' + && typeof val.next === 'function'; } -function padZeros(val, tok) { - if (tok.isPadded) { - var diff = Math.abs(tok.maxLen - String(val).length); - switch (diff) { - case 0: - return ''; - case 1: - return '0'; - default: { - return '0{' + diff + '}'; - } +function isArguments(val) { + try { + if (typeof val.length === 'number' && typeof val.callee === 'function') { + return true; + } + } catch (err) { + if (err.message.indexOf('callee') !== -1) { + return true; } } - return val; + return false; } /** - * Expose `toRegexRange` + * If you need to support Safari 5-7 (8-10 yr-old browser), + * take a look at https://github.com/feross/is-buffer */ -module.exports = toRegexRange; +function isBuffer(val) { + if (val.constructor && typeof val.constructor.isBuffer === 'function') { + return val.constructor.isBuffer(val); + } + return false; +} /***/ }), -/* 419 */ +/* 418 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * repeat-element + * is-accessor-descriptor * - * Copyright (c) 2015 Jon Schlinkert. - * Licensed under the MIT license. + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. */ -module.exports = function repeat(ele, num) { - var arr = new Array(num); +var typeOf = __webpack_require__(419); - for (var i = 0; i < num; i++) { - arr[i] = ele; +// accessor descriptor properties +var accessor = { + get: 'function', + set: 'function', + configurable: 'boolean', + enumerable: 'boolean' +}; + +function isAccessorDescriptor(obj, prop) { + if (typeof prop === 'string') { + var val = Object.getOwnPropertyDescriptor(obj, prop); + return typeof val !== 'undefined'; } - return arr; -}; + if (typeOf(obj) !== 'object') { + return false; + } + if (has(obj, 'value') || has(obj, 'writable')) { + return false; + } -/***/ }), -/* 420 */ -/***/ (function(module, exports, __webpack_require__) { + if (!has(obj, 'get') || typeof obj.get !== 'function') { + return false; + } -"use strict"; + // tldr: it's valid to have "set" be undefined + // "set" might be undefined if `Object.getOwnPropertyDescriptor` + // was used to get the value, and only `get` was defined by the user + if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { + return false; + } + for (var key in obj) { + if (!accessor.hasOwnProperty(key)) { + continue; + } -var Node = __webpack_require__(421); -var utils = __webpack_require__(406); + if (typeOf(obj[key]) === accessor[key]) { + continue; + } -/** - * Braces parsers - */ + if (typeof obj[key] !== 'undefined') { + return false; + } + } + return true; +} -module.exports = function(braces, options) { - braces.parser - .set('bos', function() { - if (!this.parsed) { - this.ast = this.nodes[0] = new Node(this.ast); - } - }) +function has(obj, key) { + return {}.hasOwnProperty.call(obj, key); +} - /** - * Character parsers - */ +/** + * Expose `isAccessorDescriptor` + */ - .set('escape', function() { - var pos = this.position(); - var m = this.match(/^(?:\\(.)|\$\{)/); - if (!m) return; +module.exports = isAccessorDescriptor; - var prev = this.prev(); - var last = utils.last(prev.nodes); - var node = pos(new Node({ - type: 'text', - multiplier: 1, - val: m[0] - })); +/***/ }), +/* 419 */ +/***/ (function(module, exports) { - if (node.val === '\\\\') { - return node; - } +var toString = Object.prototype.toString; - if (node.val === '${') { - var str = this.input; - var idx = -1; - var ch; +module.exports = function kindOf(val) { + if (val === void 0) return 'undefined'; + if (val === null) return 'null'; - while ((ch = str[++idx])) { - this.consume(1); - node.val += ch; - if (ch === '\\') { - node.val += str[++idx]; - continue; - } - if (ch === '}') { - break; - } - } - } + var type = typeof val; + if (type === 'boolean') return 'boolean'; + if (type === 'string') return 'string'; + if (type === 'number') return 'number'; + if (type === 'symbol') return 'symbol'; + if (type === 'function') { + return isGeneratorFn(val) ? 'generatorfunction' : 'function'; + } - if (this.options.unescape !== false) { - node.val = node.val.replace(/\\([{}])/g, '$1'); - } + if (isArray(val)) return 'array'; + if (isBuffer(val)) return 'buffer'; + if (isArguments(val)) return 'arguments'; + if (isDate(val)) return 'date'; + if (isError(val)) return 'error'; + if (isRegexp(val)) return 'regexp'; - if (last.val === '"' && this.input.charAt(0) === '"') { - last.val = node.val; - this.consume(1); - return; - } + switch (ctorName(val)) { + case 'Symbol': return 'symbol'; + case 'Promise': return 'promise'; - return concatNodes.call(this, pos, node, prev, options); - }) + // Set, Map, WeakSet, WeakMap + case 'WeakMap': return 'weakmap'; + case 'WeakSet': return 'weakset'; + case 'Map': return 'map'; + case 'Set': return 'set'; - /** - * Brackets: "[...]" (basic, this is overridden by - * other parsers in more advanced implementations) - */ + // 8-bit typed arrays + case 'Int8Array': return 'int8array'; + case 'Uint8Array': return 'uint8array'; + case 'Uint8ClampedArray': return 'uint8clampedarray'; - .set('bracket', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^(?:\[([!^]?)([^\]]{2,}|\]\-)(\]|[^*+?]+)|\[)/); - if (!m) return; + // 16-bit typed arrays + case 'Int16Array': return 'int16array'; + case 'Uint16Array': return 'uint16array'; - var prev = this.prev(); - var val = m[0]; - var negated = m[1] ? '^' : ''; - var inner = m[2] || ''; - var close = m[3] || ''; + // 32-bit typed arrays + case 'Int32Array': return 'int32array'; + case 'Uint32Array': return 'uint32array'; + case 'Float32Array': return 'float32array'; + case 'Float64Array': return 'float64array'; + } - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } + if (isGeneratorObj(val)) { + return 'generator'; + } - var esc = this.input.slice(0, 2); - if (inner === '' && esc === '\\]') { - inner += esc; - this.consume(2); + // Non-plain objects + type = toString.call(val); + switch (type) { + case '[object Object]': return 'object'; + // iterators + case '[object Map Iterator]': return 'mapiterator'; + case '[object Set Iterator]': return 'setiterator'; + case '[object String Iterator]': return 'stringiterator'; + case '[object Array Iterator]': return 'arrayiterator'; + } - var str = this.input; - var idx = -1; - var ch; + // other + return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); +}; - while ((ch = str[++idx])) { - this.consume(1); - if (ch === ']') { - close = ch; - break; - } - inner += ch; - } - } +function ctorName(val) { + return val.constructor ? val.constructor.name : null; +} - return pos(new Node({ - type: 'bracket', - val: val, - escaped: close !== ']', - negated: negated, - inner: inner, - close: close - })); - }) +function isArray(val) { + if (Array.isArray) return Array.isArray(val); + return val instanceof Array; +} - /** - * Empty braces (we capture these early to - * speed up processing in the compiler) - */ +function isError(val) { + return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); +} - .set('multiplier', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^\{(,+(?:(\{,+\})*),*|,*(?:(\{,+\})*),+)\}/); - if (!m) return; +function isDate(val) { + if (val instanceof Date) return true; + return typeof val.toDateString === 'function' + && typeof val.getDate === 'function' + && typeof val.setDate === 'function'; +} - this.multiplier = true; - var prev = this.prev(); - var val = m[0]; +function isRegexp(val) { + if (val instanceof RegExp) return true; + return typeof val.flags === 'string' + && typeof val.ignoreCase === 'boolean' + && typeof val.multiline === 'boolean' + && typeof val.global === 'boolean'; +} - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } +function isGeneratorFn(name, val) { + return ctorName(name) === 'GeneratorFunction'; +} - var node = pos(new Node({ - type: 'text', - multiplier: 1, - match: m, - val: val - })); +function isGeneratorObj(val) { + return typeof val.throw === 'function' + && typeof val.return === 'function' + && typeof val.next === 'function'; +} - return concatNodes.call(this, pos, node, prev, options); - }) +function isArguments(val) { + try { + if (typeof val.length === 'number' && typeof val.callee === 'function') { + return true; + } + } catch (err) { + if (err.message.indexOf('callee') !== -1) { + return true; + } + } + return false; +} - /** - * Open - */ +/** + * If you need to support Safari 5-7 (8-10 yr-old browser), + * take a look at https://github.com/feross/is-buffer + */ - .set('brace.open', function() { - var pos = this.position(); - var m = this.match(/^\{(?!(?:[^\\}]?|,+)\})/); - if (!m) return; +function isBuffer(val) { + if (val.constructor && typeof val.constructor.isBuffer === 'function') { + return val.constructor.isBuffer(val); + } + return false; +} - var prev = this.prev(); - var last = utils.last(prev.nodes); - // if the last parsed character was an extglob character - // we need to _not optimize_ the brace pattern because - // it might be mistaken for an extglob by a downstream parser - if (last && last.val && isExtglobChar(last.val.slice(-1))) { - last.optimize = false; - } +/***/ }), +/* 420 */ +/***/ (function(module, exports, __webpack_require__) { - var open = pos(new Node({ - type: 'brace.open', - val: m[0] - })); +"use strict"; +/*! + * is-data-descriptor + * + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. + */ - var node = pos(new Node({ - type: 'brace', - nodes: [] - })); - node.push(open); - prev.push(node); - this.push('brace', node); - }) - /** - * Close - */ +var typeOf = __webpack_require__(421); - .set('brace.close', function() { - var pos = this.position(); - var m = this.match(/^\}/); - if (!m || !m[0]) return; +module.exports = function isDataDescriptor(obj, prop) { + // data descriptor properties + var data = { + configurable: 'boolean', + enumerable: 'boolean', + writable: 'boolean' + }; - var brace = this.pop('brace'); - var node = pos(new Node({ - type: 'brace.close', - val: m[0] - })); + if (typeOf(obj) !== 'object') { + return false; + } - if (!this.isType(brace, 'brace')) { - if (this.options.strict) { - throw new Error('missing opening "{"'); - } - node.type = 'text'; - node.multiplier = 0; - node.escaped = true; - return node; - } + if (typeof prop === 'string') { + var val = Object.getOwnPropertyDescriptor(obj, prop); + return typeof val !== 'undefined'; + } - var prev = this.prev(); - var last = utils.last(prev.nodes); - if (last.text) { - var lastNode = utils.last(last.nodes); - if (lastNode.val === ')' && /[!@*?+]\(/.test(last.text)) { - var open = last.nodes[0]; - var text = last.nodes[1]; - if (open.type === 'brace.open' && text && text.type === 'text') { - text.optimize = false; - } - } - } + if (!('value' in obj) && !('writable' in obj)) { + return false; + } - if (brace.nodes.length > 2) { - var first = brace.nodes[1]; - if (first.type === 'text' && first.val === ',') { - brace.nodes.splice(1, 1); - brace.nodes.push(first); - } - } + for (var key in obj) { + if (key === 'value') continue; - brace.push(node); - }) + if (!data.hasOwnProperty(key)) { + continue; + } - /** - * Capture boundary characters - */ + if (typeOf(obj[key]) === data[key]) { + continue; + } - .set('boundary', function() { - var pos = this.position(); - var m = this.match(/^[$^](?!\{)/); - if (!m) return; - return pos(new Node({ - type: 'text', - val: m[0] - })); - }) + if (typeof obj[key] !== 'undefined') { + return false; + } + } + return true; +}; - /** - * One or zero, non-comma characters wrapped in braces - */ - .set('nobrace', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^\{[^,]?\}/); - if (!m) return; +/***/ }), +/* 421 */ +/***/ (function(module, exports) { - var prev = this.prev(); - var val = m[0]; +var toString = Object.prototype.toString; - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } +module.exports = function kindOf(val) { + if (val === void 0) return 'undefined'; + if (val === null) return 'null'; - return pos(new Node({ - type: 'text', - multiplier: 0, - val: val - })); - }) + var type = typeof val; + if (type === 'boolean') return 'boolean'; + if (type === 'string') return 'string'; + if (type === 'number') return 'number'; + if (type === 'symbol') return 'symbol'; + if (type === 'function') { + return isGeneratorFn(val) ? 'generatorfunction' : 'function'; + } - /** - * Text - */ + if (isArray(val)) return 'array'; + if (isBuffer(val)) return 'buffer'; + if (isArguments(val)) return 'arguments'; + if (isDate(val)) return 'date'; + if (isError(val)) return 'error'; + if (isRegexp(val)) return 'regexp'; - .set('text', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^((?!\\)[^${}\[\]])+/); - if (!m) return; + switch (ctorName(val)) { + case 'Symbol': return 'symbol'; + case 'Promise': return 'promise'; - var prev = this.prev(); - var val = m[0]; + // Set, Map, WeakSet, WeakMap + case 'WeakMap': return 'weakmap'; + case 'WeakSet': return 'weakset'; + case 'Map': return 'map'; + case 'Set': return 'set'; - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } + // 8-bit typed arrays + case 'Int8Array': return 'int8array'; + case 'Uint8Array': return 'uint8array'; + case 'Uint8ClampedArray': return 'uint8clampedarray'; - var node = pos(new Node({ - type: 'text', - multiplier: 1, - val: val - })); + // 16-bit typed arrays + case 'Int16Array': return 'int16array'; + case 'Uint16Array': return 'uint16array'; - return concatNodes.call(this, pos, node, prev, options); - }); + // 32-bit typed arrays + case 'Int32Array': return 'int32array'; + case 'Uint32Array': return 'uint32array'; + case 'Float32Array': return 'float32array'; + case 'Float64Array': return 'float64array'; + } + + if (isGeneratorObj(val)) { + return 'generator'; + } + + // Non-plain objects + type = toString.call(val); + switch (type) { + case '[object Object]': return 'object'; + // iterators + case '[object Map Iterator]': return 'mapiterator'; + case '[object Set Iterator]': return 'setiterator'; + case '[object String Iterator]': return 'stringiterator'; + case '[object Array Iterator]': return 'arrayiterator'; + } + + // other + return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); }; -/** - * Returns true if the character is an extglob character. - */ +function ctorName(val) { + return val.constructor ? val.constructor.name : null; +} -function isExtglobChar(ch) { - return ch === '!' || ch === '@' || ch === '*' || ch === '?' || ch === '+'; +function isArray(val) { + if (Array.isArray) return Array.isArray(val); + return val instanceof Array; } -/** - * Combine text nodes, and calculate empty sets (`{,,}`) - * @param {Function} `pos` Function to calculate node position - * @param {Object} `node` AST node - * @return {Object} - */ +function isError(val) { + return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); +} -function concatNodes(pos, node, parent, options) { - node.orig = node.val; - var prev = this.prev(); - var last = utils.last(prev.nodes); - var isEscaped = false; +function isDate(val) { + if (val instanceof Date) return true; + return typeof val.toDateString === 'function' + && typeof val.getDate === 'function' + && typeof val.setDate === 'function'; +} - if (node.val.length > 1) { - var a = node.val.charAt(0); - var b = node.val.slice(-1); +function isRegexp(val) { + if (val instanceof RegExp) return true; + return typeof val.flags === 'string' + && typeof val.ignoreCase === 'boolean' + && typeof val.multiline === 'boolean' + && typeof val.global === 'boolean'; +} - isEscaped = (a === '"' && b === '"') - || (a === "'" && b === "'") - || (a === '`' && b === '`'); - } +function isGeneratorFn(name, val) { + return ctorName(name) === 'GeneratorFunction'; +} - if (isEscaped && options.unescape !== false) { - node.val = node.val.slice(1, node.val.length - 1); - node.escaped = true; - } +function isGeneratorObj(val) { + return typeof val.throw === 'function' + && typeof val.return === 'function' + && typeof val.next === 'function'; +} - if (node.match) { - var match = node.match[1]; - if (!match || match.indexOf('}') === -1) { - match = node.match[0]; +function isArguments(val) { + try { + if (typeof val.length === 'number' && typeof val.callee === 'function') { + return true; + } + } catch (err) { + if (err.message.indexOf('callee') !== -1) { + return true; } - - // replace each set with a single "," - var val = match.replace(/\{/g, ',').replace(/\}/g, ''); - node.multiplier *= val.length; - node.val = ''; } + return false; +} - var simpleText = last.type === 'text' - && last.multiplier === 1 - && node.multiplier === 1 - && node.val; +/** + * If you need to support Safari 5-7 (8-10 yr-old browser), + * take a look at https://github.com/feross/is-buffer + */ - if (simpleText) { - last.val += node.val; - return; +function isBuffer(val) { + if (val.constructor && typeof val.constructor.isBuffer === 'function') { + return val.constructor.isBuffer(val); } - - prev.push(node); + return false; } /***/ }), -/* 421 */ +/* 422 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(411); -var define = __webpack_require__(398); -var utils = __webpack_require__(422); -var ownNames; +var typeOf = __webpack_require__(409); +var utils = module.exports; /** - * Create a new AST `Node` with the given `val` and `type`. - * - * ```js - * var node = new Node('*', 'Star'); - * var node = new Node({type: 'star', val: '*'}); - * ``` - * @name Node - * @param {String|Object} `val` Pass a matched substring, or an object to merge onto the node. - * @param {String} `type` The node type to use when `val` is a string. - * @return {Object} node instance - * @api public - */ - -function Node(val, type, parent) { - if (typeof type !== 'string') { - parent = type; - type = null; - } - - define(this, 'parent', parent); - define(this, 'isNode', true); - define(this, 'expect', null); - - if (typeof type !== 'string' && isObject(val)) { - lazyKeys(); - var keys = Object.keys(val); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (ownNames.indexOf(key) === -1) { - this[key] = val[key]; - } - } - } else { - this.type = type; - this.val = val; - } -} - -/** - * Returns true if the given value is a node. - * - * ```js - * var Node = require('snapdragon-node'); - * var node = new Node({type: 'foo'}); - * console.log(Node.isNode(node)); //=> true - * console.log(Node.isNode({})); //=> false - * ``` - * @param {Object} `node` - * @returns {Boolean} - * @api public - */ - -Node.isNode = function(node) { - return utils.isNode(node); -}; - -/** - * Define a non-enumberable property on the node instance. - * Useful for adding properties that shouldn't be extended - * or visible during debugging. - * - * ```js - * var node = new Node(); - * node.define('foo', 'something non-enumerable'); - * ``` - * @param {String} `name` - * @param {any} `val` - * @return {Object} returns the node instance - * @api public - */ - -Node.prototype.define = function(name, val) { - define(this, name, val); - return this; -}; - -/** - * Returns true if `node.val` is an empty string, or `node.nodes` does - * not contain any non-empty text nodes. - * - * ```js - * var node = new Node({type: 'text'}); - * node.isEmpty(); //=> true - * node.val = 'foo'; - * node.isEmpty(); //=> false - * ``` - * @param {Function} `fn` (optional) Filter function that is called on `node` and/or child nodes. `isEmpty` will return false immediately when the filter function returns false on any nodes. - * @return {Boolean} - * @api public - */ - -Node.prototype.isEmpty = function(fn) { - return utils.isEmpty(this, fn); -}; - -/** - * Given node `foo` and node `bar`, push node `bar` onto `foo.nodes`, and - * set `foo` as `bar.parent`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * foo.push(bar); - * ``` - * @param {Object} `node` - * @return {Number} Returns the length of `node.nodes` - * @api public - */ - -Node.prototype.push = function(node) { - assert(Node.isNode(node), 'expected node to be an instance of Node'); - define(node, 'parent', this); - - this.nodes = this.nodes || []; - return this.nodes.push(node); -}; - -/** - * Given node `foo` and node `bar`, unshift node `bar` onto `foo.nodes`, and - * set `foo` as `bar.parent`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * foo.unshift(bar); - * ``` - * @param {Object} `node` - * @return {Number} Returns the length of `node.nodes` - * @api public - */ - -Node.prototype.unshift = function(node) { - assert(Node.isNode(node), 'expected node to be an instance of Node'); - define(node, 'parent', this); - - this.nodes = this.nodes || []; - return this.nodes.unshift(node); -}; - -/** - * Pop a node from `node.nodes`. - * - * ```js - * var node = new Node({type: 'foo'}); - * node.push(new Node({type: 'a'})); - * node.push(new Node({type: 'b'})); - * node.push(new Node({type: 'c'})); - * node.push(new Node({type: 'd'})); - * console.log(node.nodes.length); - * //=> 4 - * node.pop(); - * console.log(node.nodes.length); - * //=> 3 - * ``` - * @return {Number} Returns the popped `node` - * @api public - */ - -Node.prototype.pop = function() { - return this.nodes && this.nodes.pop(); -}; - -/** - * Shift a node from `node.nodes`. - * - * ```js - * var node = new Node({type: 'foo'}); - * node.push(new Node({type: 'a'})); - * node.push(new Node({type: 'b'})); - * node.push(new Node({type: 'c'})); - * node.push(new Node({type: 'd'})); - * console.log(node.nodes.length); - * //=> 4 - * node.shift(); - * console.log(node.nodes.length); - * //=> 3 - * ``` - * @return {Object} Returns the shifted `node` - * @api public - */ - -Node.prototype.shift = function() { - return this.nodes && this.nodes.shift(); -}; - -/** - * Remove `node` from `node.nodes`. - * - * ```js - * node.remove(childNode); - * ``` - * @param {Object} `node` - * @return {Object} Returns the removed node. - * @api public - */ - -Node.prototype.remove = function(node) { - assert(Node.isNode(node), 'expected node to be an instance of Node'); - this.nodes = this.nodes || []; - var idx = node.index; - if (idx !== -1) { - node.index = -1; - return this.nodes.splice(idx, 1); - } - return null; -}; - -/** - * Get the first child node from `node.nodes` that matches the given `type`. - * If `type` is a number, the child node at that index is returned. - * - * ```js - * var child = node.find(1); //<= index of the node to get - * var child = node.find('foo'); //<= node.type of a child node - * var child = node.find(/^(foo|bar)$/); //<= regex to match node.type - * var child = node.find(['foo', 'bar']); //<= array of node.type(s) - * ``` - * @param {String} `type` - * @return {Object} Returns a child node or undefined. - * @api public - */ - -Node.prototype.find = function(type) { - return utils.findNode(this.nodes, type); -}; - -/** - * Return true if the node is the given `type`. - * - * ```js - * var node = new Node({type: 'bar'}); - * cosole.log(node.isType('foo')); // false - * cosole.log(node.isType(/^(foo|bar)$/)); // true - * cosole.log(node.isType(['foo', 'bar'])); // true - * ``` - * @param {String} `type` - * @return {Boolean} - * @api public - */ - -Node.prototype.isType = function(type) { - return utils.isType(this, type); -}; - -/** - * Return true if the `node.nodes` has the given `type`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * foo.push(bar); - * - * cosole.log(foo.hasType('qux')); // false - * cosole.log(foo.hasType(/^(qux|bar)$/)); // true - * cosole.log(foo.hasType(['qux', 'bar'])); // true - * ``` - * @param {String} `type` - * @return {Boolean} - * @api public - */ - -Node.prototype.hasType = function(type) { - return utils.hasType(this, type); -}; - -/** - * Get the siblings array, or `null` if it doesn't exist. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * foo.push(bar); - * foo.push(baz); - * - * console.log(bar.siblings.length) // 2 - * console.log(baz.siblings.length) // 2 - * ``` - * @return {Array} - * @api public - */ - -Object.defineProperty(Node.prototype, 'siblings', { - set: function() { - throw new Error('node.siblings is a getter and cannot be defined'); - }, - get: function() { - return this.parent ? this.parent.nodes : null; - } -}); - -/** - * Get the node's current index from `node.parent.nodes`. - * This should always be correct, even when the parent adds nodes. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.unshift(qux); - * - * console.log(bar.index) // 1 - * console.log(baz.index) // 2 - * console.log(qux.index) // 0 - * ``` - * @return {Number} - * @api public - */ - -Object.defineProperty(Node.prototype, 'index', { - set: function(index) { - define(this, 'idx', index); - }, - get: function() { - if (!Array.isArray(this.siblings)) { - return -1; - } - var tok = this.idx !== -1 ? this.siblings[this.idx] : null; - if (tok !== this) { - this.idx = this.siblings.indexOf(this); - } - return this.idx; - } -}); - -/** - * Get the previous node from the siblings array or `null`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * foo.push(bar); - * foo.push(baz); - * - * console.log(baz.prev.type) // 'bar' - * ``` - * @return {Object} - * @api public - */ - -Object.defineProperty(Node.prototype, 'prev', { - set: function() { - throw new Error('node.prev is a getter and cannot be defined'); - }, - get: function() { - if (Array.isArray(this.siblings)) { - return this.siblings[this.index - 1] || this.parent.prev; - } - return null; - } -}); - -/** - * Get the siblings array, or `null` if it doesn't exist. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * foo.push(bar); - * foo.push(baz); - * - * console.log(bar.siblings.length) // 2 - * console.log(baz.siblings.length) // 2 - * ``` - * @return {Object} - * @api public - */ - -Object.defineProperty(Node.prototype, 'next', { - set: function() { - throw new Error('node.next is a getter and cannot be defined'); - }, - get: function() { - if (Array.isArray(this.siblings)) { - return this.siblings[this.index + 1] || this.parent.next; - } - return null; - } -}); - -/** - * Get the first node from `node.nodes`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.push(qux); - * - * console.log(foo.first.type) // 'bar' - * ``` - * @return {Object} The first node, or undefiend - * @api public - */ - -Object.defineProperty(Node.prototype, 'first', { - get: function() { - return this.nodes ? this.nodes[0] : null; - } -}); - -/** - * Get the last node from `node.nodes`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.push(qux); - * - * console.log(foo.last.type) // 'qux' - * ``` - * @return {Object} The last node, or undefiend - * @api public - */ - -Object.defineProperty(Node.prototype, 'last', { - get: function() { - return this.nodes ? utils.last(this.nodes) : null; - } -}); - -/** - * Get the last node from `node.nodes`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.push(qux); - * - * console.log(foo.last.type) // 'qux' - * ``` - * @return {Object} The last node, or undefiend - * @api public - */ - -Object.defineProperty(Node.prototype, 'scope', { - get: function() { - if (this.isScope !== true) { - return this.parent ? this.parent.scope : this; - } - return this; - } -}); - -/** - * Get own property names from Node prototype, but only the - * first time `Node` is instantiated - */ - -function lazyKeys() { - if (!ownNames) { - ownNames = Object.getOwnPropertyNames(Node.prototype); - } -} - -/** - * Simplified assertion. Throws an error is `val` is falsey. - */ - -function assert(val, message) { - if (!val) throw new Error(message); -} - -/** - * Expose `Node` - */ - -exports = module.exports = Node; - - -/***/ }), -/* 422 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var typeOf = __webpack_require__(416); -var utils = module.exports; - -/** - * Returns true if the given value is a node. + * Returns true if the given value is a node. * * ```js * var Node = require('snapdragon-node'); @@ -39409,17 +39423,18 @@ function assert(val, message) { "use strict"; +var extend = __webpack_require__(394); var Snapdragon = __webpack_require__(424); -var compilers = __webpack_require__(405); -var parsers = __webpack_require__(420); -var utils = __webpack_require__(406); +var compilers = __webpack_require__(398); +var parsers = __webpack_require__(413); +var utils = __webpack_require__(399); /** * Customize Snapdragon parser and renderer */ function Braces(options) { - this.options = utils.extend({}, options); + this.options = extend({}, options); } /** @@ -39427,6 +39442,8 @@ function Braces(options) { */ Braces.prototype.init = function(options) { + if (this.isInitialized) return; + this.isInitialized = true; var opts = utils.createOptions({}, this.options, options); this.snapdragon = this.options.snapdragon || new Snapdragon(opts); this.compiler = this.snapdragon.compiler; @@ -39462,24 +39479,13 @@ Braces.prototype.init = function(options) { }); }; -/** - * Lazily initialize braces - */ - -Braces.prototype.lazyInit = function(options) { - if (!this.isInitialized) { - this.isInitialized = true; - this.init(options); - } -}; - /** * Decorate `.parse` method */ Braces.prototype.parse = function(ast, options) { - if (utils.isObject(ast) && ast.nodes) return ast; - this.lazyInit(options); + if (ast && typeof ast === 'object' && ast.nodes) return ast; + this.init(options); return this.snapdragon.parse(ast, options); }; @@ -39491,10 +39497,9 @@ Braces.prototype.compile = function(ast, options) { if (typeof ast === 'string') { ast = this.parse(ast, options); } else { - this.lazyInit(options); + this.init(options); } - var res = this.snapdragon.compile(ast, options); - return res; + return this.snapdragon.compile(ast, options); }; /** @@ -39530,10 +39535,10 @@ module.exports = Braces; var Base = __webpack_require__(425); -var define = __webpack_require__(473); -var Compiler = __webpack_require__(480); -var Parser = __webpack_require__(517); -var utils = __webpack_require__(497); +var define = __webpack_require__(386); +var Compiler = __webpack_require__(455); +var Parser = __webpack_require__(485); +var utils = __webpack_require__(465); var regexCache = {}; var cache = {}; @@ -39711,13 +39716,13 @@ module.exports.Parser = Parser; var util = __webpack_require__(29); -var define = __webpack_require__(398); -var CacheBase = __webpack_require__(426); -var Emitter = __webpack_require__(427); -var isObject = __webpack_require__(411); -var merge = __webpack_require__(445); -var pascal = __webpack_require__(448); -var cu = __webpack_require__(449); +var define = __webpack_require__(426); +var CacheBase = __webpack_require__(427); +var Emitter = __webpack_require__(428); +var isObject = __webpack_require__(404); +var merge = __webpack_require__(446); +var pascal = __webpack_require__(449); +var cu = __webpack_require__(450); /** * Optionally define a custom `cache` namespace to use. @@ -40149,18 +40154,56 @@ module.exports.namespace = namespace; /* 426 */ /***/ (function(module, exports, __webpack_require__) { +"use strict"; +/*! + * define-property + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ + + + +var isDescriptor = __webpack_require__(416); + +module.exports = function defineProperty(obj, prop, val) { + if (typeof obj !== 'object' && typeof obj !== 'function') { + throw new TypeError('expected an object or function.'); + } + + if (typeof prop !== 'string') { + throw new TypeError('expected `prop` to be a string.'); + } + + if (isDescriptor(val) && ('set' in val || 'get' in val)) { + return Object.defineProperty(obj, prop, val); + } + + return Object.defineProperty(obj, prop, { + configurable: true, + enumerable: false, + writable: true, + value: val + }); +}; + + +/***/ }), +/* 427 */ +/***/ (function(module, exports, __webpack_require__) { + "use strict"; -var isObject = __webpack_require__(411); -var Emitter = __webpack_require__(427); -var visit = __webpack_require__(428); -var toPath = __webpack_require__(431); -var union = __webpack_require__(432); -var del = __webpack_require__(436); -var get = __webpack_require__(434); -var has = __webpack_require__(441); -var set = __webpack_require__(444); +var isObject = __webpack_require__(404); +var Emitter = __webpack_require__(428); +var visit = __webpack_require__(429); +var toPath = __webpack_require__(432); +var union = __webpack_require__(433); +var del = __webpack_require__(437); +var get = __webpack_require__(435); +var has = __webpack_require__(442); +var set = __webpack_require__(445); /** * Create a `Cache` constructor that when instantiated will @@ -40414,7 +40457,7 @@ module.exports.namespace = namespace; /***/ }), -/* 427 */ +/* 428 */ /***/ (function(module, exports, __webpack_require__) { @@ -40583,7 +40626,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 428 */ +/* 429 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40596,8 +40639,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(429); -var mapVisit = __webpack_require__(430); +var visit = __webpack_require__(430); +var mapVisit = __webpack_require__(431); module.exports = function(collection, method, val) { var result; @@ -40620,7 +40663,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 429 */ +/* 430 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40633,7 +40676,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(411); +var isObject = __webpack_require__(404); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -40660,14 +40703,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 430 */ +/* 431 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var visit = __webpack_require__(429); +var visit = __webpack_require__(430); /** * Map `visit` over an array of objects. @@ -40675,2188 +40718,41 @@ var visit = __webpack_require__(429); * @param {Object} `collection` The context in which to invoke `method` * @param {String} `method` Name of the method to call on `collection` * @param {Object} `arr` Array of objects. - */ - -module.exports = function mapVisit(collection, method, val) { - if (isObject(val)) { - return visit.apply(null, arguments); - } - - if (!Array.isArray(val)) { - throw new TypeError('expected an array: ' + util.inspect(val)); - } - - var args = [].slice.call(arguments, 3); - - for (var i = 0; i < val.length; i++) { - var ele = val[i]; - if (isObject(ele)) { - visit.apply(null, [collection, method, ele].concat(args)); - } else { - collection[method].apply(collection, [ele].concat(args)); - } - } -}; - -function isObject(val) { - return val && (typeof val === 'function' || (!Array.isArray(val) && typeof val === 'object')); -} - - -/***/ }), -/* 431 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * to-object-path - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(416); - -module.exports = function toPath(args) { - if (typeOf(args) !== 'arguments') { - args = arguments; - } - return filter(args).join('.'); -}; - -function filter(arr) { - var len = arr.length; - var idx = -1; - var res = []; - - while (++idx < len) { - var ele = arr[idx]; - if (typeOf(ele) === 'arguments' || Array.isArray(ele)) { - res.push.apply(res, filter(ele)); - } else if (typeof ele === 'string') { - res.push(ele); - } - } - return res; -} - - -/***/ }), -/* 432 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isObject = __webpack_require__(395); -var union = __webpack_require__(433); -var get = __webpack_require__(434); -var set = __webpack_require__(435); - -module.exports = function unionValue(obj, prop, value) { - if (!isObject(obj)) { - throw new TypeError('union-value expects the first argument to be an object.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('union-value expects `prop` to be a string.'); - } - - var arr = arrayify(get(obj, prop)); - set(obj, prop, union(arr, arrayify(value))); - return obj; -}; - -function arrayify(val) { - if (val === null || typeof val === 'undefined') { - return []; - } - if (Array.isArray(val)) { - return val; - } - return [val]; -} - - -/***/ }), -/* 433 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -module.exports = function union(init) { - if (!Array.isArray(init)) { - throw new TypeError('arr-union expects the first argument to be an array.'); - } - - var len = arguments.length; - var i = 0; - - while (++i < len) { - var arg = arguments[i]; - if (!arg) continue; - - if (!Array.isArray(arg)) { - arg = [arg]; - } - - for (var j = 0; j < arg.length; j++) { - var ele = arg[j]; - - if (init.indexOf(ele) >= 0) { - continue; - } - init.push(ele); - } - } - return init; -}; - - -/***/ }), -/* 434 */ -/***/ (function(module, exports) { - -/*! - * get-value - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - -module.exports = function(obj, prop, a, b, c) { - if (!isObject(obj) || !prop) { - return obj; - } - - prop = toString(prop); - - // allowing for multiple properties to be passed as - // a string or array, but much faster (3-4x) than doing - // `[].slice.call(arguments)` - if (a) prop += '.' + toString(a); - if (b) prop += '.' + toString(b); - if (c) prop += '.' + toString(c); - - if (prop in obj) { - return obj[prop]; - } - - var segs = prop.split('.'); - var len = segs.length; - var i = -1; - - while (obj && (++i < len)) { - var key = segs[i]; - while (key[key.length - 1] === '\\') { - key = key.slice(0, -1) + '.' + segs[++i]; - } - obj = obj[key]; - } - return obj; -}; - -function isObject(val) { - return val !== null && (typeof val === 'object' || typeof val === 'function'); -} - -function toString(val) { - if (!val) return ''; - if (Array.isArray(val)) { - return val.join('.'); - } - return val; -} - - -/***/ }), -/* 435 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * set-value - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var toPath = __webpack_require__(431); -var extend = __webpack_require__(394); -var isPlainObject = __webpack_require__(410); -var isObject = __webpack_require__(395); - -module.exports = function(obj, path, val) { - if (!isObject(obj)) { - return obj; - } - - if (Array.isArray(path)) { - path = toPath(path); - } - - if (typeof path !== 'string') { - return obj; - } - - var segs = path.split('.'); - var len = segs.length, i = -1; - var res = obj; - var last; - - while (++i < len) { - var key = segs[i]; - - while (key[key.length - 1] === '\\') { - key = key.slice(0, -1) + '.' + segs[++i]; - } - - if (i === len - 1) { - last = key; - break; - } - - if (!isObject(obj[key])) { - obj[key] = {}; - } - obj = obj[key]; - } - - if (obj.hasOwnProperty(last) && isObject(obj[last])) { - if (isPlainObject(val)) { - extend(obj[last], val); - } else { - obj[last] = val; - } - - } else { - obj[last] = val; - } - return res; -}; - - - -/***/ }), -/* 436 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * unset-value - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isObject = __webpack_require__(411); -var has = __webpack_require__(437); - -module.exports = function unset(obj, prop) { - if (!isObject(obj)) { - throw new TypeError('expected an object.'); - } - if (obj.hasOwnProperty(prop)) { - delete obj[prop]; - return true; - } - - if (has(obj, prop)) { - var segs = prop.split('.'); - var last = segs.pop(); - while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { - last = segs.pop().slice(0, -1) + '.' + last; - } - while (segs.length) obj = obj[prop = segs.shift()]; - return (delete obj[last]); - } - return true; -}; - - -/***/ }), -/* 437 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * has-value - * - * Copyright (c) 2014-2016, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isObject = __webpack_require__(438); -var hasValues = __webpack_require__(440); -var get = __webpack_require__(434); - -module.exports = function(obj, prop, noZero) { - if (isObject(obj)) { - return hasValues(get(obj, prop), noZero); - } - return hasValues(obj, prop); -}; - - -/***/ }), -/* 438 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * isobject - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isArray = __webpack_require__(439); - -module.exports = function isObject(val) { - return val != null && typeof val === 'object' && isArray(val) === false; -}; - - -/***/ }), -/* 439 */ -/***/ (function(module, exports) { - -var toString = {}.toString; - -module.exports = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; -}; - - -/***/ }), -/* 440 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * has-values - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -module.exports = function hasValue(o, noZero) { - if (o === null || o === undefined) { - return false; - } - - if (typeof o === 'boolean') { - return true; - } - - if (typeof o === 'number') { - if (o === 0 && noZero === true) { - return false; - } - return true; - } - - if (o.length !== undefined) { - return o.length !== 0; - } - - for (var key in o) { - if (o.hasOwnProperty(key)) { - return true; - } - } - return false; -}; - - -/***/ }), -/* 441 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * has-value - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isObject = __webpack_require__(411); -var hasValues = __webpack_require__(442); -var get = __webpack_require__(434); - -module.exports = function(val, prop) { - return hasValues(isObject(val) && prop ? get(val, prop) : val); -}; - - -/***/ }), -/* 442 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * has-values - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(443); -var isNumber = __webpack_require__(415); - -module.exports = function hasValue(val) { - // is-number checks for NaN and other edge cases - if (isNumber(val)) { - return true; - } - - switch (typeOf(val)) { - case 'null': - case 'boolean': - case 'function': - return true; - case 'string': - case 'arguments': - return val.length !== 0; - case 'error': - return val.message !== ''; - case 'array': - var len = val.length; - if (len === 0) { - return false; - } - for (var i = 0; i < len; i++) { - if (hasValue(val[i])) { - return true; - } - } - return false; - case 'file': - case 'map': - case 'set': - return val.size !== 0; - case 'object': - var keys = Object.keys(val); - if (keys.length === 0) { - return false; - } - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (hasValue(val[key])) { - return true; - } - } - return false; - default: { - return false; - } - } -}; - - -/***/ }), -/* 443 */ -/***/ (function(module, exports, __webpack_require__) { - -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - var type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - - -/***/ }), -/* 444 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * set-value - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var split = __webpack_require__(407); -var extend = __webpack_require__(394); -var isPlainObject = __webpack_require__(410); -var isObject = __webpack_require__(395); - -module.exports = function(obj, prop, val) { - if (!isObject(obj)) { - return obj; - } - - if (Array.isArray(prop)) { - prop = [].concat.apply([], prop).join('.'); - } - - if (typeof prop !== 'string') { - return obj; - } - - var keys = split(prop, {sep: '.', brackets: true}); - var len = keys.length; - var idx = -1; - var current = obj; - - while (++idx < len) { - var key = keys[idx]; - if (idx !== len - 1) { - if (!isObject(current[key])) { - current[key] = {}; - } - current = current[key]; - continue; - } - - if (isPlainObject(current[key]) && isPlainObject(val)) { - current[key] = extend({}, current[key], val); - } else { - current[key] = val; - } - } - - return obj; -}; - - -/***/ }), -/* 445 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isExtendable = __webpack_require__(446); -var forIn = __webpack_require__(447); - -function mixinDeep(target, objects) { - var len = arguments.length, i = 0; - while (++i < len) { - var obj = arguments[i]; - if (isObject(obj)) { - forIn(obj, copy, target); - } - } - return target; -} - -/** - * Copy properties from the source object to the - * target object. - * - * @param {*} `val` - * @param {String} `key` - */ - -function copy(val, key) { - var obj = this[key]; - if (isObject(val) && isObject(obj)) { - mixinDeep(obj, val); - } else { - this[key] = val; - } -} - -/** - * Returns true if `val` is an object or function. - * - * @param {any} val - * @return {Boolean} - */ - -function isObject(val) { - return isExtendable(val) && !Array.isArray(val); -} - -/** - * Expose `mixinDeep` - */ - -module.exports = mixinDeep; - - -/***/ }), -/* 446 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isPlainObject = __webpack_require__(410); - -module.exports = function isExtendable(val) { - return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); -}; - - -/***/ }), -/* 447 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * for-in - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -module.exports = function forIn(obj, fn, thisArg) { - for (var key in obj) { - if (fn.call(thisArg, obj[key], key, obj) === false) { - break; - } - } -}; - - -/***/ }), -/* 448 */ -/***/ (function(module, exports) { - -/*! - * pascalcase - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - -function pascalcase(str) { - if (typeof str !== 'string') { - throw new TypeError('expected a string.'); - } - str = str.replace(/([A-Z])/g, ' $1'); - if (str.length === 1) { return str.toUpperCase(); } - str = str.replace(/^[\W_]+|[\W_]+$/g, '').toLowerCase(); - str = str.charAt(0).toUpperCase() + str.slice(1); - return str.replace(/[\W_]+(\w|$)/g, function (_, ch) { - return ch.toUpperCase(); - }); -} - -module.exports = pascalcase; - - -/***/ }), -/* 449 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var util = __webpack_require__(29); -var utils = __webpack_require__(450); - -/** - * Expose class utils - */ - -var cu = module.exports; - -/** - * Expose class utils: `cu` - */ - -cu.isObject = function isObject(val) { - return utils.isObj(val) || typeof val === 'function'; -}; - -/** - * Returns true if an array has any of the given elements, or an - * object has any of the give keys. - * - * ```js - * cu.has(['a', 'b', 'c'], 'c'); - * //=> true - * - * cu.has(['a', 'b', 'c'], ['c', 'z']); - * //=> true - * - * cu.has({a: 'b', c: 'd'}, ['c', 'z']); - * //=> true - * ``` - * @param {Object} `obj` - * @param {String|Array} `val` - * @return {Boolean} - * @api public - */ - -cu.has = function has(obj, val) { - val = cu.arrayify(val); - var len = val.length; - - if (cu.isObject(obj)) { - for (var key in obj) { - if (val.indexOf(key) > -1) { - return true; - } - } - - var keys = cu.nativeKeys(obj); - return cu.has(keys, val); - } - - if (Array.isArray(obj)) { - var arr = obj; - while (len--) { - if (arr.indexOf(val[len]) > -1) { - return true; - } - } - return false; - } - - throw new TypeError('expected an array or object.'); -}; - -/** - * Returns true if an array or object has all of the given values. - * - * ```js - * cu.hasAll(['a', 'b', 'c'], 'c'); - * //=> true - * - * cu.hasAll(['a', 'b', 'c'], ['c', 'z']); - * //=> false - * - * cu.hasAll({a: 'b', c: 'd'}, ['c', 'z']); - * //=> false - * ``` - * @param {Object|Array} `val` - * @param {String|Array} `values` - * @return {Boolean} - * @api public - */ - -cu.hasAll = function hasAll(val, values) { - values = cu.arrayify(values); - var len = values.length; - while (len--) { - if (!cu.has(val, values[len])) { - return false; - } - } - return true; -}; - -/** - * Cast the given value to an array. - * - * ```js - * cu.arrayify('foo'); - * //=> ['foo'] - * - * cu.arrayify(['foo']); - * //=> ['foo'] - * ``` - * - * @param {String|Array} `val` - * @return {Array} - * @api public - */ - -cu.arrayify = function arrayify(val) { - return val ? (Array.isArray(val) ? val : [val]) : []; -}; - -/** - * Noop - */ - -cu.noop = function noop() { - return; -}; - -/** - * Returns the first argument passed to the function. - */ - -cu.identity = function identity(val) { - return val; -}; - -/** - * Returns true if a value has a `contructor` - * - * ```js - * cu.hasConstructor({}); - * //=> true - * - * cu.hasConstructor(Object.create(null)); - * //=> false - * ``` - * @param {Object} `value` - * @return {Boolean} - * @api public - */ - -cu.hasConstructor = function hasConstructor(val) { - return cu.isObject(val) && typeof val.constructor !== 'undefined'; -}; - -/** - * Get the native `ownPropertyNames` from the constructor of the - * given `object`. An empty array is returned if the object does - * not have a constructor. - * - * ```js - * cu.nativeKeys({a: 'b', b: 'c', c: 'd'}) - * //=> ['a', 'b', 'c'] - * - * cu.nativeKeys(function(){}) - * //=> ['length', 'caller'] - * ``` - * - * @param {Object} `obj` Object that has a `constructor`. - * @return {Array} Array of keys. - * @api public - */ - -cu.nativeKeys = function nativeKeys(val) { - if (!cu.hasConstructor(val)) return []; - return Object.getOwnPropertyNames(val); -}; - -/** - * Returns property descriptor `key` if it's an "own" property - * of the given object. - * - * ```js - * function App() {} - * Object.defineProperty(App.prototype, 'count', { - * get: function() { - * return Object.keys(this).length; - * } - * }); - * cu.getDescriptor(App.prototype, 'count'); - * // returns: - * // { - * // get: [Function], - * // set: undefined, - * // enumerable: false, - * // configurable: false - * // } - * ``` - * - * @param {Object} `obj` - * @param {String} `key` - * @return {Object} Returns descriptor `key` - * @api public - */ - -cu.getDescriptor = function getDescriptor(obj, key) { - if (!cu.isObject(obj)) { - throw new TypeError('expected an object.'); - } - if (typeof key !== 'string') { - throw new TypeError('expected key to be a string.'); - } - return Object.getOwnPropertyDescriptor(obj, key); -}; - -/** - * Copy a descriptor from one object to another. - * - * ```js - * function App() {} - * Object.defineProperty(App.prototype, 'count', { - * get: function() { - * return Object.keys(this).length; - * } - * }); - * var obj = {}; - * cu.copyDescriptor(obj, App.prototype, 'count'); - * ``` - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String} `name` - * @return {Object} - * @api public - */ - -cu.copyDescriptor = function copyDescriptor(receiver, provider, name) { - if (!cu.isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!cu.isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - if (typeof name !== 'string') { - throw new TypeError('expected name to be a string.'); - } - - var val = cu.getDescriptor(provider, name); - if (val) Object.defineProperty(receiver, name, val); -}; - -/** - * Copy static properties, prototype properties, and descriptors - * from one object to another. - * - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String|Array} `omit` One or more properties to omit - * @return {Object} - * @api public - */ - -cu.copy = function copy(receiver, provider, omit) { - if (!cu.isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!cu.isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - var props = Object.getOwnPropertyNames(provider); - var keys = Object.keys(provider); - var len = props.length, - key; - omit = cu.arrayify(omit); - - while (len--) { - key = props[len]; - - if (cu.has(keys, key)) { - utils.define(receiver, key, provider[key]); - } else if (!(key in receiver) && !cu.has(omit, key)) { - cu.copyDescriptor(receiver, provider, key); - } - } -}; - -/** - * Inherit the static properties, prototype properties, and descriptors - * from of an object. - * - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String|Array} `omit` One or more properties to omit - * @return {Object} - * @api public - */ - -cu.inherit = function inherit(receiver, provider, omit) { - if (!cu.isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!cu.isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - - var keys = []; - for (var key in provider) { - keys.push(key); - receiver[key] = provider[key]; - } - - keys = keys.concat(cu.arrayify(omit)); - - var a = provider.prototype || provider; - var b = receiver.prototype || receiver; - cu.copy(b, a, keys); -}; - -/** - * Returns a function for extending the static properties, - * prototype properties, and descriptors from the `Parent` - * constructor onto `Child` constructors. - * - * ```js - * var extend = cu.extend(Parent); - * Parent.extend(Child); - * - * // optional methods - * Parent.extend(Child, { - * foo: function() {}, - * bar: function() {} - * }); - * ``` - * @param {Function} `Parent` Parent ctor - * @param {Function} `extend` Optional extend function to handle custom extensions. Useful when updating methods that require a specific prototype. - * @param {Function} `Child` Child ctor - * @param {Object} `proto` Optionally pass additional prototype properties to inherit. - * @return {Object} - * @api public - */ - -cu.extend = function() { - // keep it lazy, instead of assigning to `cu.extend` - return utils.staticExtend.apply(null, arguments); -}; - -/** - * Bubble up events emitted from static methods on the Parent ctor. - * - * @param {Object} `Parent` - * @param {Array} `events` Event names to bubble up - * @api public - */ - -cu.bubble = function(Parent, events) { - events = events || []; - Parent.bubble = function(Child, arr) { - if (Array.isArray(arr)) { - events = utils.union([], events, arr); - } - var len = events.length; - var idx = -1; - while (++idx < len) { - var name = events[idx]; - Parent.on(name, Child.emit.bind(Child, name)); - } - cu.bubble(Child, events); - }; -}; - - -/***/ }), -/* 450 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var utils = {}; - - - -/** - * Lazily required module dependencies - */ - -utils.union = __webpack_require__(433); -utils.define = __webpack_require__(451); -utils.isObj = __webpack_require__(411); -utils.staticExtend = __webpack_require__(458); - - -/** - * Expose `utils` - */ - -module.exports = utils; - - -/***/ }), -/* 451 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isDescriptor = __webpack_require__(452); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } - - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; - - -/***/ }), -/* 452 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(453); -var isAccessor = __webpack_require__(454); -var isData = __webpack_require__(456); - -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; - } - if ('get' in obj) { - return isAccessor(obj, key); - } - return isData(obj, key); -}; - - -/***/ }), -/* 453 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - var type = typeof val; - - // primitivies - if (type === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (type === 'string' || val instanceof String) { - return 'string'; - } - if (type === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (type === 'function' || val instanceof Function) { - if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { - return 'generatorfunction'; - } - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - if (type === '[object Map Iterator]') { - return 'mapiterator'; - } - if (type === '[object Set Iterator]') { - return 'setiterator'; - } - if (type === '[object String Iterator]') { - return 'stringiterator'; - } - if (type === '[object Array Iterator]') { - return 'arrayiterator'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - return val.constructor - && typeof val.constructor.isBuffer === 'function' - && val.constructor.isBuffer(val); -} - - -/***/ }), -/* 454 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-accessor-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(455); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; - -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (typeOf(obj) !== 'object') { - return false; - } - - if (has(obj, 'value') || has(obj, 'writable')) { - return false; - } - - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; - } - - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } - - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === accessor[key]) { - continue; - } - - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -} - -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} - -/** - * Expose `isAccessorDescriptor` - */ - -module.exports = isAccessorDescriptor; - - -/***/ }), -/* 455 */ -/***/ (function(module, exports, __webpack_require__) { - -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - var type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - - -/***/ }), -/* 456 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-data-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(457); - -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' -}; - -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } - - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (!('value' in obj) && !('writable' in obj)) { - return false; - } - - for (var key in obj) { - if (key === 'value') continue; - - if (!data.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === data[key]) { - continue; - } - - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -} - -/** - * Expose `isDataDescriptor` - */ - -module.exports = isDataDescriptor; - - -/***/ }), -/* 457 */ -/***/ (function(module, exports, __webpack_require__) { - -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - var type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - - -/***/ }), -/* 458 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * static-extend - * - * Copyright (c) 2016, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var copy = __webpack_require__(459); -var define = __webpack_require__(466); -var util = __webpack_require__(29); - -/** - * Returns a function for extending the static properties, - * prototype properties, and descriptors from the `Parent` - * constructor onto `Child` constructors. - * - * ```js - * var extend = require('static-extend'); - * Parent.extend = extend(Parent); - * - * // optionally pass a custom merge function as the second arg - * Parent.extend = extend(Parent, function(Child) { - * Child.prototype.mixin = function(key, val) { - * Child.prototype[key] = val; - * }; - * }); - * - * // extend "child" constructors - * Parent.extend(Child); - * - * // optionally define prototype methods as the second arg - * Parent.extend(Child, { - * foo: function() {}, - * bar: function() {} - * }); - * ``` - * @param {Function} `Parent` Parent ctor - * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype. - * @param {Function} `Child` Child ctor - * @param {Object} `proto` Optionally pass additional prototype properties to inherit. - * @return {Object} - * @api public - */ - -function extend(Parent, extendFn) { - if (typeof Parent !== 'function') { - throw new TypeError('expected Parent to be a function.'); - } - - return function(Ctor, proto) { - if (typeof Ctor !== 'function') { - throw new TypeError('expected Ctor to be a function.'); - } - - util.inherits(Ctor, Parent); - copy(Ctor, Parent); - - // proto can be null or a plain object - if (typeof proto === 'object') { - var obj = Object.create(proto); - - for (var k in obj) { - Ctor.prototype[k] = obj[k]; - } - } - - // keep a reference to the parent prototype - define(Ctor.prototype, '_parent_', { - configurable: true, - set: function() {}, - get: function() { - return Parent.prototype; - } - }); - - if (typeof extendFn === 'function') { - extendFn(Ctor, Parent); - } - - Ctor.extend = extend(Ctor, extendFn); - }; -}; - -/** - * Expose `extend` - */ - -module.exports = extend; - - -/***/ }), -/* 459 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var typeOf = __webpack_require__(416); -var copyDescriptor = __webpack_require__(460); -var define = __webpack_require__(461); - -/** - * Copy static properties, prototype properties, and descriptors from one object to another. - * - * ```js - * function App() {} - * var proto = App.prototype; - * App.prototype.set = function() {}; - * App.prototype.get = function() {}; - * - * var obj = {}; - * copy(obj, proto); - * ``` - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String|Array} `omit` One or more properties to omit - * @return {Object} - * @api public - */ - -function copy(receiver, provider, omit) { - if (!isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - - var props = nativeKeys(provider); - var keys = Object.keys(provider); - var len = props.length; - omit = arrayify(omit); - - while (len--) { - var key = props[len]; - - if (has(keys, key)) { - define(receiver, key, provider[key]); - } else if (!(key in receiver) && !has(omit, key)) { - copyDescriptor(receiver, provider, key); - } - } -}; - -/** - * Return true if the given value is an object or function - */ - -function isObject(val) { - return typeOf(val) === 'object' || typeof val === 'function'; -} - -/** - * Returns true if an array has any of the given elements, or an - * object has any of the give keys. - * - * ```js - * has(['a', 'b', 'c'], 'c'); - * //=> true - * - * has(['a', 'b', 'c'], ['c', 'z']); - * //=> true - * - * has({a: 'b', c: 'd'}, ['c', 'z']); - * //=> true - * ``` - * @param {Object} `obj` - * @param {String|Array} `val` - * @return {Boolean} - */ - -function has(obj, val) { - val = arrayify(val); - var len = val.length; - - if (isObject(obj)) { - for (var key in obj) { - if (val.indexOf(key) > -1) { - return true; - } - } - - var keys = nativeKeys(obj); - return has(keys, val); - } - - if (Array.isArray(obj)) { - var arr = obj; - while (len--) { - if (arr.indexOf(val[len]) > -1) { - return true; - } - } - return false; - } - - throw new TypeError('expected an array or object.'); -} - -/** - * Cast the given value to an array. - * - * ```js - * arrayify('foo'); - * //=> ['foo'] - * - * arrayify(['foo']); - * //=> ['foo'] - * ``` - * - * @param {String|Array} `val` - * @return {Array} - */ - -function arrayify(val) { - return val ? (Array.isArray(val) ? val : [val]) : []; -} - -/** - * Returns true if a value has a `contructor` - * - * ```js - * hasConstructor({}); - * //=> true - * - * hasConstructor(Object.create(null)); - * //=> false - * ``` - * @param {Object} `value` - * @return {Boolean} - */ - -function hasConstructor(val) { - return isObject(val) && typeof val.constructor !== 'undefined'; -} - -/** - * Get the native `ownPropertyNames` from the constructor of the - * given `object`. An empty array is returned if the object does - * not have a constructor. - * - * ```js - * nativeKeys({a: 'b', b: 'c', c: 'd'}) - * //=> ['a', 'b', 'c'] - * - * nativeKeys(function(){}) - * //=> ['length', 'caller'] - * ``` - * - * @param {Object} `obj` Object that has a `constructor`. - * @return {Array} Array of keys. - */ - -function nativeKeys(val) { - if (!hasConstructor(val)) return []; - return Object.getOwnPropertyNames(val); -} - -/** - * Expose `copy` - */ - -module.exports = copy; - -/** - * Expose `copy.has` for tests - */ - -module.exports.has = has; - - -/***/ }), -/* 460 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * copy-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -/** - * Copy a descriptor from one object to another. - * - * ```js - * function App() { - * this.cache = {}; - * } - * App.prototype.set = function(key, val) { - * this.cache[key] = val; - * return this; - * }; - * Object.defineProperty(App.prototype, 'count', { - * get: function() { - * return Object.keys(this.cache).length; - * } - * }); - * - * copy(App.prototype, 'count', 'len'); - * - * // create an instance - * var app = new App(); - * - * app.set('a', true); - * app.set('b', true); - * app.set('c', true); - * - * console.log(app.count); - * //=> 3 - * console.log(app.len); - * //=> 3 - * ``` - * @name copy - * @param {Object} `receiver` The target object - * @param {Object} `provider` The provider object - * @param {String} `from` The key to copy on provider. - * @param {String} `to` Optionally specify a new key name to use. - * @return {Object} - * @api public - */ - -module.exports = function copyDescriptor(receiver, provider, from, to) { - if (!isObject(provider) && typeof provider !== 'function') { - to = from; - from = provider; - provider = receiver; - } - if (!isObject(receiver) && typeof receiver !== 'function') { - throw new TypeError('expected the first argument to be an object'); - } - if (!isObject(provider) && typeof provider !== 'function') { - throw new TypeError('expected provider to be an object'); - } + */ - if (typeof to !== 'string') { - to = from; - } - if (typeof from !== 'string') { - throw new TypeError('expected key to be a string'); +module.exports = function mapVisit(collection, method, val) { + if (isObject(val)) { + return visit.apply(null, arguments); } - if (!(from in provider)) { - throw new Error('property "' + from + '" does not exist'); + if (!Array.isArray(val)) { + throw new TypeError('expected an array: ' + util.inspect(val)); } - var val = Object.getOwnPropertyDescriptor(provider, from); - if (val) Object.defineProperty(receiver, to, val); + var args = [].slice.call(arguments, 3); + + for (var i = 0; i < val.length; i++) { + var ele = val[i]; + if (isObject(ele)) { + visit.apply(null, [collection, method, ele].concat(args)); + } else { + collection[method].apply(collection, [ele].concat(args)); + } + } }; function isObject(val) { - return {}.toString.call(val) === '[object Object]'; + return val && (typeof val === 'function' || (!Array.isArray(val) && typeof val === 'object')); } - /***/ }), -/* 461 */ +/* 432 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * define-property + * to-object-path * * Copyright (c) 2015, Jon Schlinkert. * Licensed under the MIT License. @@ -42864,421 +40760,466 @@ function isObject(val) { -var isDescriptor = __webpack_require__(462); +var typeOf = __webpack_require__(409); -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); +module.exports = function toPath(args) { + if (typeOf(args) !== 'arguments') { + args = arguments; } + return filter(args).join('.'); +}; - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } +function filter(arr) { + var len = arr.length; + var idx = -1; + var res = []; - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); + while (++idx < len) { + var ele = arr[idx]; + if (typeOf(ele) === 'arguments' || Array.isArray(ele)) { + res.push.apply(res, filter(ele)); + } else if (typeof ele === 'string') { + res.push(ele); + } } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; + return res; +} /***/ }), -/* 462 */ +/* 433 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ +var isObject = __webpack_require__(395); +var union = __webpack_require__(434); +var get = __webpack_require__(435); +var set = __webpack_require__(436); -var typeOf = __webpack_require__(463); -var isAccessor = __webpack_require__(464); -var isData = __webpack_require__(465); - -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; +module.exports = function unionValue(obj, prop, value) { + if (!isObject(obj)) { + throw new TypeError('union-value expects the first argument to be an object.'); } - if ('get' in obj) { - return isAccessor(obj, key); + + if (typeof prop !== 'string') { + throw new TypeError('union-value expects `prop` to be a string.'); } - return isData(obj, key); + + var arr = arrayify(get(obj, prop)); + set(obj, prop, union(arr, arrayify(value))); + return obj; }; +function arrayify(val) { + if (val === null || typeof val === 'undefined') { + return []; + } + if (Array.isArray(val)) { + return val; + } + return [val]; +} + /***/ }), -/* 463 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; +/* 434 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ +"use strict"; -module.exports = function kindOf(val) { - var type = typeof val; - // primitivies - if (type === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (type === 'string' || val instanceof String) { - return 'string'; - } - if (type === 'number' || val instanceof Number) { - return 'number'; +module.exports = function union(init) { + if (!Array.isArray(init)) { + throw new TypeError('arr-union expects the first argument to be an array.'); } - // functions - if (type === 'function' || val instanceof Function) { - if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { - return 'generatorfunction'; + var len = arguments.length; + var i = 0; + + while (++i < len) { + var arg = arguments[i]; + if (!arg) continue; + + if (!Array.isArray(arg)) { + arg = [arg]; } - return 'function'; - } - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } + for (var j = 0; j < arg.length; j++) { + var ele = arg[j]; - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; + if (init.indexOf(ele) >= 0) { + continue; + } + init.push(ele); + } } + return init; +}; - // other objects - type = toString.call(val); - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } +/***/ }), +/* 435 */ +/***/ (function(module, exports) { - // buffer - if (isBuffer(val)) { - return 'buffer'; - } +/*! + * get-value + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - if (type === '[object Map Iterator]') { - return 'mapiterator'; - } - if (type === '[object Set Iterator]') { - return 'setiterator'; - } - if (type === '[object String Iterator]') { - return 'stringiterator'; - } - if (type === '[object Array Iterator]') { - return 'arrayiterator'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; +module.exports = function(obj, prop, a, b, c) { + if (!isObject(obj) || !prop) { + return obj; } - if (type === '[object Float64Array]') { - return 'float64array'; + + prop = toString(prop); + + // allowing for multiple properties to be passed as + // a string or array, but much faster (3-4x) than doing + // `[].slice.call(arguments)` + if (a) prop += '.' + toString(a); + if (b) prop += '.' + toString(b); + if (c) prop += '.' + toString(c); + + if (prop in obj) { + return obj[prop]; } - // must be a plain object - return 'object'; + var segs = prop.split('.'); + var len = segs.length; + var i = -1; + + while (obj && (++i < len)) { + var key = segs[i]; + while (key[key.length - 1] === '\\') { + key = key.slice(0, -1) + '.' + segs[++i]; + } + obj = obj[key]; + } + return obj; }; -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ +function isObject(val) { + return val !== null && (typeof val === 'object' || typeof val === 'function'); +} -function isBuffer(val) { - return val.constructor - && typeof val.constructor.isBuffer === 'function' - && val.constructor.isBuffer(val); +function toString(val) { + if (!val) return ''; + if (Array.isArray(val)) { + return val.join('.'); + } + return val; } /***/ }), -/* 464 */ +/* 436 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-accessor-descriptor + * set-value * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * Copyright (c) 2014-2015, 2017, Jon Schlinkert. + * Released under the MIT License. */ -var typeOf = __webpack_require__(416); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; +var toPath = __webpack_require__(432); +var extend = __webpack_require__(394); +var isPlainObject = __webpack_require__(403); +var isObject = __webpack_require__(395); -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; +module.exports = function(obj, path, val) { + if (!isObject(obj)) { + return obj; } - if (typeOf(obj) !== 'object') { - return false; + if (Array.isArray(path)) { + path = toPath(path); } - if (has(obj, 'value') || has(obj, 'writable')) { - return false; + if (typeof path !== 'string') { + return obj; } - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; - } + var segs = path.split('.'); + var len = segs.length, i = -1; + var res = obj; + var last; - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } + while (++i < len) { + var key = segs[i]; - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; + while (key[key.length - 1] === '\\') { + key = key.slice(0, -1) + '.' + segs[++i]; } - if (typeOf(obj[key]) === accessor[key]) { - continue; + if (i === len - 1) { + last = key; + break; } - if (typeof obj[key] !== 'undefined') { - return false; + if (!isObject(obj[key])) { + obj[key] = {}; + } + obj = obj[key]; + } + + if (obj.hasOwnProperty(last) && isObject(obj[last])) { + if (isPlainObject(val)) { + extend(obj[last], val); + } else { + obj[last] = val; + } + + } else { + obj[last] = val; + } + return res; +}; + + + +/***/ }), +/* 437 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * unset-value + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ + + + +var isObject = __webpack_require__(404); +var has = __webpack_require__(438); + +module.exports = function unset(obj, prop) { + if (!isObject(obj)) { + throw new TypeError('expected an object.'); + } + if (obj.hasOwnProperty(prop)) { + delete obj[prop]; + return true; + } + + if (has(obj, prop)) { + var segs = prop.split('.'); + var last = segs.pop(); + while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { + last = segs.pop().slice(0, -1) + '.' + last; } + while (segs.length) obj = obj[prop = segs.shift()]; + return (delete obj[last]); } return true; -} +}; -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} -/** - * Expose `isAccessorDescriptor` +/***/ }), +/* 438 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * has-value + * + * Copyright (c) 2014-2016, Jon Schlinkert. + * Licensed under the MIT License. */ -module.exports = isAccessorDescriptor; + + +var isObject = __webpack_require__(439); +var hasValues = __webpack_require__(441); +var get = __webpack_require__(435); + +module.exports = function(obj, prop, noZero) { + if (isObject(obj)) { + return hasValues(get(obj, prop), noZero); + } + return hasValues(obj, prop); +}; /***/ }), -/* 465 */ +/* 439 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-data-descriptor + * isobject * - * Copyright (c) 2015, Jon Schlinkert. + * Copyright (c) 2014-2015, Jon Schlinkert. * Licensed under the MIT License. */ -var typeOf = __webpack_require__(416); +var isArray = __webpack_require__(440); -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' +module.exports = function isObject(val) { + return val != null && typeof val === 'object' && isArray(val) === false; }; -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } +/***/ }), +/* 440 */ +/***/ (function(module, exports) { - if (!('value' in obj) && !('writable' in obj)) { - return false; - } +var toString = {}.toString; - for (var key in obj) { - if (key === 'value') continue; +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; - if (!data.hasOwnProperty(key)) { - continue; - } - if (typeOf(obj[key]) === data[key]) { - continue; - } +/***/ }), +/* 441 */ +/***/ (function(module, exports, __webpack_require__) { - if (typeof obj[key] !== 'undefined') { +"use strict"; +/*! + * has-values + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + + + +module.exports = function hasValue(o, noZero) { + if (o === null || o === undefined) { + return false; + } + + if (typeof o === 'boolean') { + return true; + } + + if (typeof o === 'number') { + if (o === 0 && noZero === true) { return false; } + return true; } - return true; -} -/** - * Expose `isDataDescriptor` - */ + if (o.length !== undefined) { + return o.length !== 0; + } -module.exports = isDataDescriptor; + for (var key in o) { + if (o.hasOwnProperty(key)) { + return true; + } + } + return false; +}; /***/ }), -/* 466 */ +/* 442 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * define-property + * has-value * - * Copyright (c) 2015, Jon Schlinkert. + * Copyright (c) 2014-2017, Jon Schlinkert. * Licensed under the MIT License. */ -var isDescriptor = __webpack_require__(467); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } +var isObject = __webpack_require__(404); +var hasValues = __webpack_require__(443); +var get = __webpack_require__(435); - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); +module.exports = function(val, prop) { + return hasValues(isObject(val) && prop ? get(val, prop) : val); }; /***/ }), -/* 467 */ +/* 443 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-descriptor + * has-values * - * Copyright (c) 2015-2017, Jon Schlinkert. + * Copyright (c) 2014-2015, 2017, Jon Schlinkert. * Released under the MIT License. */ -var typeOf = __webpack_require__(468); -var isAccessor = __webpack_require__(469); -var isData = __webpack_require__(471); +var typeOf = __webpack_require__(444); +var isNumber = __webpack_require__(408); -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; +module.exports = function hasValue(val) { + // is-number checks for NaN and other edge cases + if (isNumber(val)) { + return true; } - if ('get' in obj) { - return isAccessor(obj, key); + + switch (typeOf(val)) { + case 'null': + case 'boolean': + case 'function': + return true; + case 'string': + case 'arguments': + return val.length !== 0; + case 'error': + return val.message !== ''; + case 'array': + var len = val.length; + if (len === 0) { + return false; + } + for (var i = 0; i < len; i++) { + if (hasValue(val[i])) { + return true; + } + } + return false; + case 'file': + case 'map': + case 'set': + return val.size !== 0; + case 'object': + var keys = Object.keys(val); + if (keys.length === 0) { + return false; + } + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (hasValue(val[key])) { + return true; + } + } + return false; + default: { + return false; + } } - return isData(obj, key); }; /***/ }), -/* 468 */ -/***/ (function(module, exports) { +/* 444 */ +/***/ (function(module, exports, __webpack_require__) { +var isBuffer = __webpack_require__(391); var toString = Object.prototype.toString; /** @@ -43289,10 +41230,8 @@ var toString = Object.prototype.toString; */ module.exports = function kindOf(val) { - var type = typeof val; - // primitivies - if (type === 'undefined') { + if (typeof val === 'undefined') { return 'undefined'; } if (val === null) { @@ -43301,18 +41240,15 @@ module.exports = function kindOf(val) { if (val === true || val === false || val instanceof Boolean) { return 'boolean'; } - if (type === 'string' || val instanceof String) { + if (typeof val === 'string' || val instanceof String) { return 'string'; } - if (type === 'number' || val instanceof Number) { + if (typeof val === 'number' || val instanceof Number) { return 'number'; } // functions - if (type === 'function' || val instanceof Function) { - if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { - return 'generatorfunction'; - } + if (typeof val === 'function' || val instanceof Function) { return 'function'; } @@ -43330,7 +41266,7 @@ module.exports = function kindOf(val) { } // other objects - type = toString.call(val); + var type = toString.call(val); if (type === '[object RegExp]') { return 'regexp'; @@ -43369,20 +41305,7 @@ module.exports = function kindOf(val) { if (type === '[object Symbol]') { return 'symbol'; } - - if (type === '[object Map Iterator]') { - return 'mapiterator'; - } - if (type === '[object Set Iterator]') { - return 'setiterator'; - } - if (type === '[object String Iterator]') { - return 'stringiterator'; - } - if (type === '[object Array Iterator]') { - return 'arrayiterator'; - } - + // typed arrays if (type === '[object Int8Array]') { return 'int8array'; @@ -43416,1013 +41339,969 @@ module.exports = function kindOf(val) { return 'object'; }; -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - return val.constructor - && typeof val.constructor.isBuffer === 'function' - && val.constructor.isBuffer(val); -} - /***/ }), -/* 469 */ +/* 445 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-accessor-descriptor + * set-value * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * Copyright (c) 2014-2015, 2017, Jon Schlinkert. + * Released under the MIT License. */ -var typeOf = __webpack_require__(470); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; - -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } +var split = __webpack_require__(400); +var extend = __webpack_require__(394); +var isPlainObject = __webpack_require__(403); +var isObject = __webpack_require__(395); - if (typeOf(obj) !== 'object') { - return false; +module.exports = function(obj, prop, val) { + if (!isObject(obj)) { + return obj; } - if (has(obj, 'value') || has(obj, 'writable')) { - return false; + if (Array.isArray(prop)) { + prop = [].concat.apply([], prop).join('.'); } - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; + if (typeof prop !== 'string') { + return obj; } - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } + var keys = split(prop, {sep: '.', brackets: true}); + var len = keys.length; + var idx = -1; + var current = obj; - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { + while (++idx < len) { + var key = keys[idx]; + if (idx !== len - 1) { + if (!isObject(current[key])) { + current[key] = {}; + } + current = current[key]; continue; } - if (typeOf(obj[key]) === accessor[key]) { - continue; + if (isPlainObject(current[key]) && isPlainObject(val)) { + current[key] = extend({}, current[key], val); + } else { + current[key] = val; } + } - if (typeof obj[key] !== 'undefined') { - return false; + return obj; +}; + + +/***/ }), +/* 446 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var isExtendable = __webpack_require__(447); +var forIn = __webpack_require__(448); + +function mixinDeep(target, objects) { + var len = arguments.length, i = 0; + while (++i < len) { + var obj = arguments[i]; + if (isObject(obj)) { + forIn(obj, copy, target); } } - return true; + return target; } -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); +/** + * Copy properties from the source object to the + * target object. + * + * @param {*} `val` + * @param {String} `key` + */ + +function copy(val, key) { + var obj = this[key]; + if (isObject(val) && isObject(obj)) { + mixinDeep(obj, val); + } else { + this[key] = val; + } } /** - * Expose `isAccessorDescriptor` + * Returns true if `val` is an object or function. + * + * @param {any} val + * @return {Boolean} */ -module.exports = isAccessorDescriptor; +function isObject(val) { + return isExtendable(val) && !Array.isArray(val); +} + +/** + * Expose `mixinDeep` + */ + +module.exports = mixinDeep; /***/ }), -/* 470 */ +/* 447 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. +"use strict"; +/*! + * is-extendable * - * @param {*} `val` - * @return {*} Native javascript type + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. */ -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } +var isPlainObject = __webpack_require__(403); - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } +module.exports = function isExtendable(val) { + return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); +}; - // other objects - var type = toString.call(val); - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } +/***/ }), +/* 448 */ +/***/ (function(module, exports, __webpack_require__) { - // buffer - if (isBuffer(val)) { - return 'buffer'; - } +"use strict"; +/*! + * for-in + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - // must be a plain object - return 'object'; +module.exports = function forIn(obj, fn, thisArg) { + for (var key in obj) { + if (fn.call(thisArg, obj[key], key, obj) === false) { + break; + } + } }; /***/ }), -/* 471 */ -/***/ (function(module, exports, __webpack_require__) { +/* 449 */ +/***/ (function(module, exports) { -"use strict"; /*! - * is-data-descriptor + * pascalcase * * Copyright (c) 2015, Jon Schlinkert. * Licensed under the MIT License. */ +function pascalcase(str) { + if (typeof str !== 'string') { + throw new TypeError('expected a string.'); + } + str = str.replace(/([A-Z])/g, ' $1'); + if (str.length === 1) { return str.toUpperCase(); } + str = str.replace(/^[\W_]+|[\W_]+$/g, '').toLowerCase(); + str = str.charAt(0).toUpperCase() + str.slice(1); + return str.replace(/[\W_]+(\w|$)/g, function (_, ch) { + return ch.toUpperCase(); + }); +} + +module.exports = pascalcase; + +/***/ }), +/* 450 */ +/***/ (function(module, exports, __webpack_require__) { -var typeOf = __webpack_require__(472); +"use strict"; -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' + +var util = __webpack_require__(29); +var utils = __webpack_require__(451); + +/** + * Expose class utils + */ + +var cu = module.exports; + +/** + * Expose class utils: `cu` + */ + +cu.isObject = function isObject(val) { + return utils.isObj(val) || typeof val === 'function'; }; -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } +/** + * Returns true if an array has any of the given elements, or an + * object has any of the give keys. + * + * ```js + * cu.has(['a', 'b', 'c'], 'c'); + * //=> true + * + * cu.has(['a', 'b', 'c'], ['c', 'z']); + * //=> true + * + * cu.has({a: 'b', c: 'd'}, ['c', 'z']); + * //=> true + * ``` + * @param {Object} `obj` + * @param {String|Array} `val` + * @return {Boolean} + * @api public + */ - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; +cu.has = function has(obj, val) { + val = cu.arrayify(val); + var len = val.length; + + if (cu.isObject(obj)) { + for (var key in obj) { + if (val.indexOf(key) > -1) { + return true; + } + } + + var keys = cu.nativeKeys(obj); + return cu.has(keys, val); } - if (!('value' in obj) && !('writable' in obj)) { + if (Array.isArray(obj)) { + var arr = obj; + while (len--) { + if (arr.indexOf(val[len]) > -1) { + return true; + } + } return false; } - for (var key in obj) { - if (key === 'value') continue; - - if (!data.hasOwnProperty(key)) { - continue; - } + throw new TypeError('expected an array or object.'); +}; - if (typeOf(obj[key]) === data[key]) { - continue; - } +/** + * Returns true if an array or object has all of the given values. + * + * ```js + * cu.hasAll(['a', 'b', 'c'], 'c'); + * //=> true + * + * cu.hasAll(['a', 'b', 'c'], ['c', 'z']); + * //=> false + * + * cu.hasAll({a: 'b', c: 'd'}, ['c', 'z']); + * //=> false + * ``` + * @param {Object|Array} `val` + * @param {String|Array} `values` + * @return {Boolean} + * @api public + */ - if (typeof obj[key] !== 'undefined') { +cu.hasAll = function hasAll(val, values) { + values = cu.arrayify(values); + var len = values.length; + while (len--) { + if (!cu.has(val, values[len])) { return false; } } return true; -} +}; /** - * Expose `isDataDescriptor` + * Cast the given value to an array. + * + * ```js + * cu.arrayify('foo'); + * //=> ['foo'] + * + * cu.arrayify(['foo']); + * //=> ['foo'] + * ``` + * + * @param {String|Array} `val` + * @return {Array} + * @api public */ -module.exports = isDataDescriptor; +cu.arrayify = function arrayify(val) { + return val ? (Array.isArray(val) ? val : [val]) : []; +}; +/** + * Noop + */ -/***/ }), -/* 472 */ -/***/ (function(module, exports, __webpack_require__) { +cu.noop = function noop() { + return; +}; -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; +/** + * Returns the first argument passed to the function. + */ + +cu.identity = function identity(val) { + return val; +}; /** - * Get the native `typeof` a value. + * Returns true if a value has a `contructor` * - * @param {*} `val` - * @return {*} Native javascript type + * ```js + * cu.hasConstructor({}); + * //=> true + * + * cu.hasConstructor(Object.create(null)); + * //=> false + * ``` + * @param {Object} `value` + * @return {Boolean} + * @api public */ -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } +cu.hasConstructor = function hasConstructor(val) { + return cu.isObject(val) && typeof val.constructor !== 'undefined'; +}; - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } +/** + * Get the native `ownPropertyNames` from the constructor of the + * given `object`. An empty array is returned if the object does + * not have a constructor. + * + * ```js + * cu.nativeKeys({a: 'b', b: 'c', c: 'd'}) + * //=> ['a', 'b', 'c'] + * + * cu.nativeKeys(function(){}) + * //=> ['length', 'caller'] + * ``` + * + * @param {Object} `obj` Object that has a `constructor`. + * @return {Array} Array of keys. + * @api public + */ - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } +cu.nativeKeys = function nativeKeys(val) { + if (!cu.hasConstructor(val)) return []; + return Object.getOwnPropertyNames(val); +}; - // other objects - var type = toString.call(val); +/** + * Returns property descriptor `key` if it's an "own" property + * of the given object. + * + * ```js + * function App() {} + * Object.defineProperty(App.prototype, 'count', { + * get: function() { + * return Object.keys(this).length; + * } + * }); + * cu.getDescriptor(App.prototype, 'count'); + * // returns: + * // { + * // get: [Function], + * // set: undefined, + * // enumerable: false, + * // configurable: false + * // } + * ``` + * + * @param {Object} `obj` + * @param {String} `key` + * @return {Object} Returns descriptor `key` + * @api public + */ - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; +cu.getDescriptor = function getDescriptor(obj, key) { + if (!cu.isObject(obj)) { + throw new TypeError('expected an object.'); } - - // buffer - if (isBuffer(val)) { - return 'buffer'; + if (typeof key !== 'string') { + throw new TypeError('expected key to be a string.'); } + return Object.getOwnPropertyDescriptor(obj, key); +}; - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } +/** + * Copy a descriptor from one object to another. + * + * ```js + * function App() {} + * Object.defineProperty(App.prototype, 'count', { + * get: function() { + * return Object.keys(this).length; + * } + * }); + * var obj = {}; + * cu.copyDescriptor(obj, App.prototype, 'count'); + * ``` + * @param {Object} `receiver` + * @param {Object} `provider` + * @param {String} `name` + * @return {Object} + * @api public + */ - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; +cu.copyDescriptor = function copyDescriptor(receiver, provider, name) { + if (!cu.isObject(receiver)) { + throw new TypeError('expected receiving object to be an object.'); } - if (type === '[object Float32Array]') { - return 'float32array'; + if (!cu.isObject(provider)) { + throw new TypeError('expected providing object to be an object.'); } - if (type === '[object Float64Array]') { - return 'float64array'; + if (typeof name !== 'string') { + throw new TypeError('expected name to be a string.'); } - // must be a plain object - return 'object'; + var val = cu.getDescriptor(provider, name); + if (val) Object.defineProperty(receiver, name, val); }; - -/***/ }), -/* 473 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property +/** + * Copy static properties, prototype properties, and descriptors + * from one object to another. * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * @param {Object} `receiver` + * @param {Object} `provider` + * @param {String|Array} `omit` One or more properties to omit + * @return {Object} + * @api public */ - - -var isDescriptor = __webpack_require__(474); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); +cu.copy = function copy(receiver, provider, omit) { + if (!cu.isObject(receiver)) { + throw new TypeError('expected receiving object to be an object.'); } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); + if (!cu.isObject(provider)) { + throw new TypeError('expected providing object to be an object.'); } + var props = Object.getOwnPropertyNames(provider); + var keys = Object.keys(provider); + var len = props.length, + key; + omit = cu.arrayify(omit); - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } + while (len--) { + key = props[len]; - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); + if (cu.has(keys, key)) { + utils.define(receiver, key, provider[key]); + } else if (!(key in receiver) && !cu.has(omit, key)) { + cu.copyDescriptor(receiver, provider, key); + } + } }; - -/***/ }), -/* 474 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-descriptor +/** + * Inherit the static properties, prototype properties, and descriptors + * from of an object. * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. + * @param {Object} `receiver` + * @param {Object} `provider` + * @param {String|Array} `omit` One or more properties to omit + * @return {Object} + * @api public */ - - -var typeOf = __webpack_require__(475); -var isAccessor = __webpack_require__(476); -var isData = __webpack_require__(478); - -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; +cu.inherit = function inherit(receiver, provider, omit) { + if (!cu.isObject(receiver)) { + throw new TypeError('expected receiving object to be an object.'); } - if ('get' in obj) { - return isAccessor(obj, key); + if (!cu.isObject(provider)) { + throw new TypeError('expected providing object to be an object.'); } - return isData(obj, key); -}; + var keys = []; + for (var key in provider) { + keys.push(key); + receiver[key] = provider[key]; + } -/***/ }), -/* 475 */ -/***/ (function(module, exports) { + keys = keys.concat(cu.arrayify(omit)); -var toString = Object.prototype.toString; + var a = provider.prototype || provider; + var b = receiver.prototype || receiver; + cu.copy(b, a, keys); +}; /** - * Get the native `typeof` a value. + * Returns a function for extending the static properties, + * prototype properties, and descriptors from the `Parent` + * constructor onto `Child` constructors. * - * @param {*} `val` - * @return {*} Native javascript type + * ```js + * var extend = cu.extend(Parent); + * Parent.extend(Child); + * + * // optional methods + * Parent.extend(Child, { + * foo: function() {}, + * bar: function() {} + * }); + * ``` + * @param {Function} `Parent` Parent ctor + * @param {Function} `extend` Optional extend function to handle custom extensions. Useful when updating methods that require a specific prototype. + * @param {Function} `Child` Child ctor + * @param {Object} `proto` Optionally pass additional prototype properties to inherit. + * @return {Object} + * @api public */ -module.exports = function kindOf(val) { - var type = typeof val; +cu.extend = function() { + // keep it lazy, instead of assigning to `cu.extend` + return utils.staticExtend.apply(null, arguments); +}; - // primitivies - if (type === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (type === 'string' || val instanceof String) { - return 'string'; - } - if (type === 'number' || val instanceof Number) { - return 'number'; - } +/** + * Bubble up events emitted from static methods on the Parent ctor. + * + * @param {Object} `Parent` + * @param {Array} `events` Event names to bubble up + * @api public + */ - // functions - if (type === 'function' || val instanceof Function) { - if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { - return 'generatorfunction'; +cu.bubble = function(Parent, events) { + events = events || []; + Parent.bubble = function(Child, arr) { + if (Array.isArray(arr)) { + events = utils.union([], events, arr); } - return 'function'; - } + var len = events.length; + var idx = -1; + while (++idx < len) { + var name = events[idx]; + Parent.on(name, Child.emit.bind(Child, name)); + } + cu.bubble(Child, events); + }; +}; - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } +/***/ }), +/* 451 */ +/***/ (function(module, exports, __webpack_require__) { - // other objects - type = toString.call(val); +"use strict"; - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } - // buffer - if (isBuffer(val)) { - return 'buffer'; - } +var utils = {}; - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - if (type === '[object Map Iterator]') { - return 'mapiterator'; - } - if (type === '[object Set Iterator]') { - return 'setiterator'; - } - if (type === '[object String Iterator]') { - return 'stringiterator'; - } - if (type === '[object Array Iterator]') { - return 'arrayiterator'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - // must be a plain object - return 'object'; -}; /** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer + * Lazily required module dependencies */ -function isBuffer(val) { - return val.constructor - && typeof val.constructor.isBuffer === 'function' - && val.constructor.isBuffer(val); -} +utils.union = __webpack_require__(434); +utils.define = __webpack_require__(386); +utils.isObj = __webpack_require__(404); +utils.staticExtend = __webpack_require__(452); + + +/** + * Expose `utils` + */ + +module.exports = utils; /***/ }), -/* 476 */ +/* 452 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-accessor-descriptor + * static-extend * - * Copyright (c) 2015, Jon Schlinkert. + * Copyright (c) 2016, Jon Schlinkert. * Licensed under the MIT License. */ -var typeOf = __webpack_require__(477); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; +var copy = __webpack_require__(453); +var define = __webpack_require__(386); +var util = __webpack_require__(29); -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } +/** + * Returns a function for extending the static properties, + * prototype properties, and descriptors from the `Parent` + * constructor onto `Child` constructors. + * + * ```js + * var extend = require('static-extend'); + * Parent.extend = extend(Parent); + * + * // optionally pass a custom merge function as the second arg + * Parent.extend = extend(Parent, function(Child) { + * Child.prototype.mixin = function(key, val) { + * Child.prototype[key] = val; + * }; + * }); + * + * // extend "child" constructors + * Parent.extend(Child); + * + * // optionally define prototype methods as the second arg + * Parent.extend(Child, { + * foo: function() {}, + * bar: function() {} + * }); + * ``` + * @param {Function} `Parent` Parent ctor + * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype. + * @param {Function} `Child` Child ctor + * @param {Object} `proto` Optionally pass additional prototype properties to inherit. + * @return {Object} + * @api public + */ - if (typeOf(obj) !== 'object') { - return false; +function extend(Parent, extendFn) { + if (typeof Parent !== 'function') { + throw new TypeError('expected Parent to be a function.'); } - if (has(obj, 'value') || has(obj, 'writable')) { - return false; - } + return function(Ctor, proto) { + if (typeof Ctor !== 'function') { + throw new TypeError('expected Ctor to be a function.'); + } - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; - } + util.inherits(Ctor, Parent); + copy(Ctor, Parent); - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } + // proto can be null or a plain object + if (typeof proto === 'object') { + var obj = Object.create(proto); - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; + for (var k in obj) { + Ctor.prototype[k] = obj[k]; + } } - if (typeOf(obj[key]) === accessor[key]) { - continue; - } + // keep a reference to the parent prototype + define(Ctor.prototype, '_parent_', { + configurable: true, + set: function() {}, + get: function() { + return Parent.prototype; + } + }); - if (typeof obj[key] !== 'undefined') { - return false; + if (typeof extendFn === 'function') { + extendFn(Ctor, Parent); } - } - return true; -} -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} + Ctor.extend = extend(Ctor, extendFn); + }; +}; /** - * Expose `isAccessorDescriptor` + * Expose `extend` */ -module.exports = isAccessorDescriptor; +module.exports = extend; /***/ }), -/* 477 */ +/* 453 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; +"use strict"; + + +var typeOf = __webpack_require__(409); +var copyDescriptor = __webpack_require__(454); +var define = __webpack_require__(386); /** - * Get the native `typeof` a value. + * Copy static properties, prototype properties, and descriptors from one object to another. * - * @param {*} `val` - * @return {*} Native javascript type + * ```js + * function App() {} + * var proto = App.prototype; + * App.prototype.set = function() {}; + * App.prototype.get = function() {}; + * + * var obj = {}; + * copy(obj, proto); + * ``` + * @param {Object} `receiver` + * @param {Object} `provider` + * @param {String|Array} `omit` One or more properties to omit + * @return {Object} + * @api public */ -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - var type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; +function copy(receiver, provider, omit) { + if (!isObject(receiver)) { + throw new TypeError('expected receiving object to be an object.'); } - if (type === '[object Error]') { - return 'error'; + if (!isObject(provider)) { + throw new TypeError('expected providing object to be an object.'); } - // buffer - if (isBuffer(val)) { - return 'buffer'; - } + var props = nativeKeys(provider); + var keys = Object.keys(provider); + var len = props.length; + omit = arrayify(omit); - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } + while (len--) { + var key = props[len]; - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; + if (has(keys, key)) { + define(receiver, key, provider[key]); + } else if (!(key in receiver) && !has(omit, key)) { + copyDescriptor(receiver, provider, key); + } } - - // must be a plain object - return 'object'; }; +/** + * Return true if the given value is an object or function + */ -/***/ }), -/* 478 */ -/***/ (function(module, exports, __webpack_require__) { +function isObject(val) { + return typeOf(val) === 'object' || typeof val === 'function'; +} -"use strict"; -/*! - * is-data-descriptor +/** + * Returns true if an array has any of the given elements, or an + * object has any of the give keys. * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * ```js + * has(['a', 'b', 'c'], 'c'); + * //=> true + * + * has(['a', 'b', 'c'], ['c', 'z']); + * //=> true + * + * has({a: 'b', c: 'd'}, ['c', 'z']); + * //=> true + * ``` + * @param {Object} `obj` + * @param {String|Array} `val` + * @return {Boolean} */ +function has(obj, val) { + val = arrayify(val); + var len = val.length; + if (isObject(obj)) { + for (var key in obj) { + if (val.indexOf(key) > -1) { + return true; + } + } -var typeOf = __webpack_require__(479); - -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' -}; - -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } - - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; + var keys = nativeKeys(obj); + return has(keys, val); } - if (!('value' in obj) && !('writable' in obj)) { + if (Array.isArray(obj)) { + var arr = obj; + while (len--) { + if (arr.indexOf(val[len]) > -1) { + return true; + } + } return false; } - for (var key in obj) { - if (key === 'value') continue; - - if (!data.hasOwnProperty(key)) { - continue; - } + throw new TypeError('expected an array or object.'); +} - if (typeOf(obj[key]) === data[key]) { - continue; - } +/** + * Cast the given value to an array. + * + * ```js + * arrayify('foo'); + * //=> ['foo'] + * + * arrayify(['foo']); + * //=> ['foo'] + * ``` + * + * @param {String|Array} `val` + * @return {Array} + */ - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; +function arrayify(val) { + return val ? (Array.isArray(val) ? val : [val]) : []; } /** - * Expose `isDataDescriptor` + * Returns true if a value has a `contructor` + * + * ```js + * hasConstructor({}); + * //=> true + * + * hasConstructor(Object.create(null)); + * //=> false + * ``` + * @param {Object} `value` + * @return {Boolean} */ -module.exports = isDataDescriptor; - +function hasConstructor(val) { + return isObject(val) && typeof val.constructor !== 'undefined'; +} -/***/ }), -/* 479 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Get the native `ownPropertyNames` from the constructor of the + * given `object`. An empty array is returned if the object does + * not have a constructor. + * + * ```js + * nativeKeys({a: 'b', b: 'c', c: 'd'}) + * //=> ['a', 'b', 'c'] + * + * nativeKeys(function(){}) + * //=> ['length', 'caller'] + * ``` + * + * @param {Object} `obj` Object that has a `constructor`. + * @return {Array} Array of keys. + */ -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; +function nativeKeys(val) { + if (!hasConstructor(val)) return []; + return Object.getOwnPropertyNames(val); +} /** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type + * Expose `copy` */ -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } +module.exports = copy; - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } +/** + * Expose `copy.has` for tests + */ - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } +module.exports.has = has; - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - // other objects - var type = toString.call(val); +/***/ }), +/* 454 */ +/***/ (function(module, exports, __webpack_require__) { - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } +"use strict"; +/*! + * copy-descriptor + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; +/** + * Copy a descriptor from one object to another. + * + * ```js + * function App() { + * this.cache = {}; + * } + * App.prototype.set = function(key, val) { + * this.cache[key] = val; + * return this; + * }; + * Object.defineProperty(App.prototype, 'count', { + * get: function() { + * return Object.keys(this.cache).length; + * } + * }); + * + * copy(App.prototype, 'count', 'len'); + * + * // create an instance + * var app = new App(); + * + * app.set('a', true); + * app.set('b', true); + * app.set('c', true); + * + * console.log(app.count); + * //=> 3 + * console.log(app.len); + * //=> 3 + * ``` + * @name copy + * @param {Object} `receiver` The target object + * @param {Object} `provider` The provider object + * @param {String} `from` The key to copy on provider. + * @param {String} `to` Optionally specify a new key name to use. + * @return {Object} + * @api public + */ + +module.exports = function copyDescriptor(receiver, provider, from, to) { + if (!isObject(provider) && typeof provider !== 'function') { + to = from; + from = provider; + provider = receiver; } - if (type === '[object Uint16Array]') { - return 'uint16array'; + if (!isObject(receiver) && typeof receiver !== 'function') { + throw new TypeError('expected the first argument to be an object'); } - if (type === '[object Int32Array]') { - return 'int32array'; + if (!isObject(provider) && typeof provider !== 'function') { + throw new TypeError('expected provider to be an object'); } - if (type === '[object Uint32Array]') { - return 'uint32array'; + + if (typeof to !== 'string') { + to = from; } - if (type === '[object Float32Array]') { - return 'float32array'; + if (typeof from !== 'string') { + throw new TypeError('expected key to be a string'); } - if (type === '[object Float64Array]') { - return 'float64array'; + + if (!(from in provider)) { + throw new Error('property "' + from + '" does not exist'); } - // must be a plain object - return 'object'; + var val = Object.getOwnPropertyDescriptor(provider, from); + if (val) Object.defineProperty(receiver, to, val); }; +function isObject(val) { + return {}.toString.call(val) === '[object Object]'; +} + + /***/ }), -/* 480 */ +/* 455 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(481); -var define = __webpack_require__(473); -var debug = __webpack_require__(490)('snapdragon:compiler'); -var utils = __webpack_require__(497); +var use = __webpack_require__(456); +var define = __webpack_require__(386); +var debug = __webpack_require__(458)('snapdragon:compiler'); +var utils = __webpack_require__(465); /** * Create a new `Compiler` with the given `options`. @@ -44572,792 +42451,190 @@ Compiler.prototype = { var opts = utils.extend({}, this.options, options); this.ast = ast; this.parsingErrors = this.ast.errors; - this.output = ''; - - // source map support - if (opts.sourcemap) { - var sourcemaps = __webpack_require__(516); - sourcemaps(this); - this.mapVisit(this.ast.nodes); - this.applySourceMaps(); - this.map = opts.sourcemap === 'generator' ? this.map : this.map.toJSON(); - return this; - } - - this.mapVisit(this.ast.nodes); - return this; - } -}; - -/** - * Expose `Compiler` - */ - -module.exports = Compiler; - - -/***/ }), -/* 481 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * use - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var utils = __webpack_require__(482); - -module.exports = function base(app, opts) { - if (!utils.isObject(app) && typeof app !== 'function') { - throw new TypeError('use: expect `app` be an object or function'); - } - - if (!utils.isObject(opts)) { - opts = {}; - } - - var prop = utils.isString(opts.prop) ? opts.prop : 'fns'; - if (!Array.isArray(app[prop])) { - utils.define(app, prop, []); - } - - /** - * Define a plugin function to be passed to use. The only - * parameter exposed to the plugin is `app`, the object or function. - * passed to `use(app)`. `app` is also exposed as `this` in plugins. - * - * Additionally, **if a plugin returns a function, the function will - * be pushed onto the `fns` array**, allowing the plugin to be - * called at a later point by the `run` method. - * - * ```js - * var use = require('use'); - * - * // define a plugin - * function foo(app) { - * // do stuff - * } - * - * var app = function(){}; - * use(app); - * - * // register plugins - * app.use(foo); - * app.use(bar); - * app.use(baz); - * ``` - * @name .use - * @param {Function} `fn` plugin function to call - * @api public - */ - - utils.define(app, 'use', use); - - /** - * Run all plugins on `fns`. Any plugin that returns a function - * when called by `use` is pushed onto the `fns` array. - * - * ```js - * var config = {}; - * app.run(config); - * ``` - * @name .run - * @param {Object} `value` Object to be modified by plugins. - * @return {Object} Returns the object passed to `run` - * @api public - */ - - utils.define(app, 'run', function(val) { - if (!utils.isObject(val)) return; - decorate(val); - - var self = this || app; - var fns = self[prop]; - var len = fns.length; - var idx = -1; - - while (++idx < len) { - val.use(fns[idx]); - } - return val; - }); - - /** - * Call plugin `fn`. If a function is returned push it into the - * `fns` array to be called by the `run` method. - */ - - function use(fn, options) { - if (typeof fn !== 'function') { - throw new TypeError('.use expects `fn` be a function'); - } - - var self = this || app; - if (typeof opts.fn === 'function') { - opts.fn.call(self, self, options); - } - - var plugin = fn.call(self, self); - if (typeof plugin === 'function') { - var fns = self[prop]; - fns.push(plugin); - } - return self; - } - - /** - * Ensure the `.use` method exists on `val` - */ - - function decorate(val) { - if (!val.use || !val.run) { - base(val); - } - } - - return app; -}; - - -/***/ }), -/* 482 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var utils = {}; - - - -/** - * Lazily required module dependencies - */ - -utils.define = __webpack_require__(483); -utils.isObject = __webpack_require__(411); - - -utils.isString = function(val) { - return val && typeof val === 'string'; -}; - -/** - * Expose `utils` modules - */ - -module.exports = utils; - - -/***/ }), -/* 483 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isDescriptor = __webpack_require__(484); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } - - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; - - -/***/ }), -/* 484 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(485); -var isAccessor = __webpack_require__(486); -var isData = __webpack_require__(488); - -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; - } - if ('get' in obj) { - return isAccessor(obj, key); - } - return isData(obj, key); -}; - - -/***/ }), -/* 485 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - var type = typeof val; - - // primitivies - if (type === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (type === 'string' || val instanceof String) { - return 'string'; - } - if (type === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (type === 'function' || val instanceof Function) { - if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { - return 'generatorfunction'; - } - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - if (type === '[object Map Iterator]') { - return 'mapiterator'; - } - if (type === '[object Set Iterator]') { - return 'setiterator'; - } - if (type === '[object String Iterator]') { - return 'stringiterator'; - } - if (type === '[object Array Iterator]') { - return 'arrayiterator'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - return val.constructor - && typeof val.constructor.isBuffer === 'function' - && val.constructor.isBuffer(val); -} - - -/***/ }), -/* 486 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-accessor-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(487); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; - -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (typeOf(obj) !== 'object') { - return false; - } - - if (has(obj, 'value') || has(obj, 'writable')) { - return false; - } - - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; - } - - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } - - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === accessor[key]) { - continue; - } + this.output = ''; - if (typeof obj[key] !== 'undefined') { - return false; + // source map support + if (opts.sourcemap) { + var sourcemaps = __webpack_require__(484); + sourcemaps(this); + this.mapVisit(this.ast.nodes); + this.applySourceMaps(); + this.map = opts.sourcemap === 'generator' ? this.map : this.map.toJSON(); + return this; } - } - return true; -} -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} + this.mapVisit(this.ast.nodes); + return this; + } +}; /** - * Expose `isAccessorDescriptor` + * Expose `Compiler` */ -module.exports = isAccessorDescriptor; +module.exports = Compiler; /***/ }), -/* 487 */ +/* 456 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. +"use strict"; +/*! + * use * - * @param {*} `val` - * @return {*} Native javascript type + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. */ -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - // other objects - var type = toString.call(val); - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } +var utils = __webpack_require__(457); - // buffer - if (isBuffer(val)) { - return 'buffer'; +module.exports = function base(app, opts) { + if (!utils.isObject(app) && typeof app !== 'function') { + throw new TypeError('use: expect `app` be an object or function'); } - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; + if (!utils.isObject(opts)) { + opts = {}; } - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; + var prop = utils.isString(opts.prop) ? opts.prop : 'fns'; + if (!Array.isArray(app[prop])) { + utils.define(app, prop, []); } - // must be a plain object - return 'object'; -}; - - -/***/ }), -/* 488 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-data-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - + /** + * Define a plugin function to be passed to use. The only + * parameter exposed to the plugin is `app`, the object or function. + * passed to `use(app)`. `app` is also exposed as `this` in plugins. + * + * Additionally, **if a plugin returns a function, the function will + * be pushed onto the `fns` array**, allowing the plugin to be + * called at a later point by the `run` method. + * + * ```js + * var use = require('use'); + * + * // define a plugin + * function foo(app) { + * // do stuff + * } + * + * var app = function(){}; + * use(app); + * + * // register plugins + * app.use(foo); + * app.use(bar); + * app.use(baz); + * ``` + * @name .use + * @param {Function} `fn` plugin function to call + * @api public + */ -var typeOf = __webpack_require__(489); + utils.define(app, 'use', use); -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' -}; + /** + * Run all plugins on `fns`. Any plugin that returns a function + * when called by `use` is pushed onto the `fns` array. + * + * ```js + * var config = {}; + * app.run(config); + * ``` + * @name .run + * @param {Object} `value` Object to be modified by plugins. + * @return {Object} Returns the object passed to `run` + * @api public + */ -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } + utils.define(app, 'run', function(val) { + if (!utils.isObject(val)) return; + decorate(val); - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } + var self = this || app; + var fns = self[prop]; + var len = fns.length; + var idx = -1; - if (!('value' in obj) && !('writable' in obj)) { - return false; - } + while (++idx < len) { + val.use(fns[idx]); + } + return val; + }); - for (var key in obj) { - if (key === 'value') continue; + /** + * Call plugin `fn`. If a function is returned push it into the + * `fns` array to be called by the `run` method. + */ - if (!data.hasOwnProperty(key)) { - continue; + function use(fn, options) { + if (typeof fn !== 'function') { + throw new TypeError('.use expects `fn` be a function'); } - if (typeOf(obj[key]) === data[key]) { - continue; + var self = this || app; + if (typeof opts.fn === 'function') { + opts.fn.call(self, self, options); } - if (typeof obj[key] !== 'undefined') { - return false; + var plugin = fn.call(self, self); + if (typeof plugin === 'function') { + var fns = self[prop]; + fns.push(plugin); } + return self; } - return true; -} -/** - * Expose `isDataDescriptor` - */ + /** + * Ensure the `.use` method exists on `val` + */ -module.exports = isDataDescriptor; + function decorate(val) { + if (!val.use || !val.run) { + base(val); + } + } + + return app; +}; /***/ }), -/* 489 */ +/* 457 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ +"use strict"; -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } +var utils = {}; - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - // other objects - var type = toString.call(val); +/** + * Lazily required module dependencies + */ - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } +utils.define = __webpack_require__(386); +utils.isObject = __webpack_require__(404); - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } +utils.isString = function(val) { + return val && typeof val === 'string'; +}; - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } +/** + * Expose `utils` modules + */ - // must be a plain object - return 'object'; -}; +module.exports = utils; /***/ }), -/* 490 */ +/* 458 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -45366,14 +42643,14 @@ module.exports = function kindOf(val) { */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(491); + module.exports = __webpack_require__(459); } else { - module.exports = __webpack_require__(494); + module.exports = __webpack_require__(462); } /***/ }), -/* 491 */ +/* 459 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -45382,7 +42659,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(492); +exports = module.exports = __webpack_require__(460); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -45564,7 +42841,7 @@ function localstorage() { /***/ }), -/* 492 */ +/* 460 */ /***/ (function(module, exports, __webpack_require__) { @@ -45580,7 +42857,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(493); +exports.humanize = __webpack_require__(461); /** * The currently active debug mode names, and names to skip. @@ -45772,7 +43049,7 @@ function coerce(val) { /***/ }), -/* 493 */ +/* 461 */ /***/ (function(module, exports) { /** @@ -45930,14 +43207,14 @@ function plural(ms, n, name) { /***/ }), -/* 494 */ +/* 462 */ /***/ (function(module, exports, __webpack_require__) { /** * Module dependencies. */ -var tty = __webpack_require__(495); +var tty = __webpack_require__(463); var util = __webpack_require__(29); /** @@ -45946,7 +43223,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(492); +exports = module.exports = __webpack_require__(460); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -46125,7 +43402,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(496); + var net = __webpack_require__(464); stream = new net.Socket({ fd: fd, readable: false, @@ -46184,19 +43461,19 @@ exports.enable(load()); /***/ }), -/* 495 */ +/* 463 */ /***/ (function(module, exports) { module.exports = require("tty"); /***/ }), -/* 496 */ +/* 464 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 497 */ +/* 465 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -46207,8 +43484,8 @@ module.exports = require("net"); */ exports.extend = __webpack_require__(394); -exports.SourceMap = __webpack_require__(498); -exports.sourceMapResolve = __webpack_require__(509); +exports.SourceMap = __webpack_require__(466); +exports.sourceMapResolve = __webpack_require__(477); /** * Convert backslash in the given string to forward slashes @@ -46251,7 +43528,7 @@ exports.last = function(arr, n) { /***/ }), -/* 498 */ +/* 466 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -46259,13 +43536,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(499).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(505).SourceMapConsumer; -exports.SourceNode = __webpack_require__(508).SourceNode; +exports.SourceMapGenerator = __webpack_require__(467).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(473).SourceMapConsumer; +exports.SourceNode = __webpack_require__(476).SourceNode; /***/ }), -/* 499 */ +/* 467 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -46275,10 +43552,10 @@ exports.SourceNode = __webpack_require__(508).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(500); -var util = __webpack_require__(502); -var ArraySet = __webpack_require__(503).ArraySet; -var MappingList = __webpack_require__(504).MappingList; +var base64VLQ = __webpack_require__(468); +var util = __webpack_require__(470); +var ArraySet = __webpack_require__(471).ArraySet; +var MappingList = __webpack_require__(472).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -46687,7 +43964,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 500 */ +/* 468 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -46727,7 +44004,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(501); +var base64 = __webpack_require__(469); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -46833,7 +44110,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 501 */ +/* 469 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -46906,7 +44183,7 @@ exports.decode = function (charCode) { /***/ }), -/* 502 */ +/* 470 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -47329,7 +44606,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 503 */ +/* 471 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -47339,7 +44616,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(502); +var util = __webpack_require__(470); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -47456,7 +44733,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 504 */ +/* 472 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -47466,7 +44743,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(502); +var util = __webpack_require__(470); /** * Determine whether mappingB is after mappingA with respect to generated @@ -47541,7 +44818,7 @@ exports.MappingList = MappingList; /***/ }), -/* 505 */ +/* 473 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -47551,11 +44828,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(502); -var binarySearch = __webpack_require__(506); -var ArraySet = __webpack_require__(503).ArraySet; -var base64VLQ = __webpack_require__(500); -var quickSort = __webpack_require__(507).quickSort; +var util = __webpack_require__(470); +var binarySearch = __webpack_require__(474); +var ArraySet = __webpack_require__(471).ArraySet; +var base64VLQ = __webpack_require__(468); +var quickSort = __webpack_require__(475).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -48629,7 +45906,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 506 */ +/* 474 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -48746,7 +46023,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 507 */ +/* 475 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -48866,7 +46143,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 508 */ +/* 476 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -48876,8 +46153,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(499).SourceMapGenerator; -var util = __webpack_require__(502); +var SourceMapGenerator = __webpack_require__(467).SourceMapGenerator; +var util = __webpack_require__(470); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -49285,17 +46562,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 509 */ +/* 477 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(510) -var resolveUrl = __webpack_require__(511) -var decodeUriComponent = __webpack_require__(512) -var urix = __webpack_require__(514) -var atob = __webpack_require__(515) +var sourceMappingURL = __webpack_require__(478) +var resolveUrl = __webpack_require__(479) +var decodeUriComponent = __webpack_require__(480) +var urix = __webpack_require__(482) +var atob = __webpack_require__(483) @@ -49593,7 +46870,7 @@ module.exports = { /***/ }), -/* 510 */ +/* 478 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -49656,7 +46933,7 @@ void (function(root, factory) { /***/ }), -/* 511 */ +/* 479 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -49674,13 +46951,13 @@ module.exports = resolveUrl /***/ }), -/* 512 */ +/* 480 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(513) +var decodeUriComponent = __webpack_require__(481) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -49691,7 +46968,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 513 */ +/* 481 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49792,7 +47069,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 514 */ +/* 482 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -49815,7 +47092,7 @@ module.exports = urix /***/ }), -/* 515 */ +/* 483 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49829,7 +47106,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 516 */ +/* 484 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49837,8 +47114,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(23); var path = __webpack_require__(16); -var define = __webpack_require__(473); -var utils = __webpack_require__(497); +var define = __webpack_require__(386); +var utils = __webpack_require__(465); /** * Expose `mixin()`. @@ -49981,19 +47258,19 @@ exports.comment = function(node) { /***/ }), -/* 517 */ +/* 485 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(481); +var use = __webpack_require__(456); var util = __webpack_require__(29); -var Cache = __webpack_require__(518); -var define = __webpack_require__(473); -var debug = __webpack_require__(490)('snapdragon:parser'); -var Position = __webpack_require__(519); -var utils = __webpack_require__(497); +var Cache = __webpack_require__(486); +var define = __webpack_require__(386); +var debug = __webpack_require__(458)('snapdragon:parser'); +var Position = __webpack_require__(487); +var utils = __webpack_require__(465); /** * Create a new `Parser` with the given `input` and `options`. @@ -50521,7 +47798,7 @@ module.exports = Parser; /***/ }), -/* 518 */ +/* 486 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50628,13 +47905,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 519 */ +/* 487 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(473); +var define = __webpack_require__(386); /** * Store position for a node @@ -50649,14 +47926,14 @@ module.exports = function Position(start, parser) { /***/ }), -/* 520 */ +/* 488 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(521); -var extglob = __webpack_require__(531); +var nanomatch = __webpack_require__(489); +var extglob = __webpack_require__(500); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -50733,7 +48010,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 521 */ +/* 489 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50751,10 +48028,10 @@ var extend = __webpack_require__(394); * Local dependencies */ -var compilers = __webpack_require__(522); -var parsers = __webpack_require__(523); -var cache = __webpack_require__(525); -var utils = __webpack_require__(527); +var compilers = __webpack_require__(490); +var parsers = __webpack_require__(491); +var cache = __webpack_require__(493); +var utils = __webpack_require__(495); var MAX_LENGTH = 1024 * 64; /** @@ -51583,7 +48860,7 @@ module.exports = nanomatch; /***/ }), -/* 522 */ +/* 490 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -51909,7 +49186,7 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 523 */ +/* 491 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -51917,7 +49194,7 @@ module.exports = function(nanomatch, options) { var regexNot = __webpack_require__(396); var toRegex = __webpack_require__(385); -var isOdd = __webpack_require__(524); +var isOdd = __webpack_require__(492); /** * Characters to use in negation regex (we want to "not" match @@ -52304,7 +49581,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 524 */ +/* 492 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52317,7 +49594,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(415); +var isNumber = __webpack_require__(408); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -52331,14 +49608,14 @@ module.exports = function isOdd(i) { /***/ }), -/* 525 */ +/* 493 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(526))(); +module.exports = new (__webpack_require__(494))(); /***/ }), -/* 526 */ +/* 494 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52351,7 +49628,7 @@ module.exports = new (__webpack_require__(526))(); -var MapCache = __webpack_require__(518); +var MapCache = __webpack_require__(486); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -52473,7 +49750,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 527 */ +/* 495 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52487,11 +49764,11 @@ var path = __webpack_require__(16); */ var Snapdragon = __webpack_require__(424); -utils.define = __webpack_require__(398); -utils.diff = __webpack_require__(528); +utils.define = __webpack_require__(496); +utils.diff = __webpack_require__(497); utils.extend = __webpack_require__(394); -utils.pick = __webpack_require__(529); -utils.typeOf = __webpack_require__(530); +utils.pick = __webpack_require__(498); +utils.typeOf = __webpack_require__(499); utils.unique = __webpack_require__(397); /** @@ -52858,7 +50135,45 @@ utils.unixify = function(options) { /***/ }), -/* 528 */ +/* 496 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * define-property + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ + + + +var isDescriptor = __webpack_require__(416); + +module.exports = function defineProperty(obj, prop, val) { + if (typeof obj !== 'object' && typeof obj !== 'function') { + throw new TypeError('expected an object or function.'); + } + + if (typeof prop !== 'string') { + throw new TypeError('expected `prop` to be a string.'); + } + + if (isDescriptor(val) && ('set' in val || 'get' in val)) { + return Object.defineProperty(obj, prop, val); + } + + return Object.defineProperty(obj, prop, { + configurable: true, + enumerable: false, + writable: true, + value: val + }); +}; + + +/***/ }), +/* 497 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52912,7 +50227,7 @@ function diffArray(one, two) { /***/ }), -/* 529 */ +/* 498 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52925,7 +50240,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(411); +var isObject = __webpack_require__(404); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -52954,7 +50269,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 530 */ +/* 499 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -53107,7 +50422,7 @@ function isBuffer(val) { /***/ }), -/* 531 */ +/* 500 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53125,10 +50440,10 @@ var toRegex = __webpack_require__(385); * Local dependencies */ -var compilers = __webpack_require__(532); -var parsers = __webpack_require__(545); -var Extglob = __webpack_require__(547); -var utils = __webpack_require__(546); +var compilers = __webpack_require__(501); +var parsers = __webpack_require__(507); +var Extglob = __webpack_require__(509); +var utils = __webpack_require__(508); var MAX_LENGTH = 1024 * 64; /** @@ -53445,13 +50760,13 @@ module.exports = extglob; /***/ }), -/* 532 */ +/* 501 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(533); +var brackets = __webpack_require__(502); /** * Extglob compilers @@ -53621,7 +50936,7 @@ module.exports = function(extglob) { /***/ }), -/* 533 */ +/* 502 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53631,14 +50946,14 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(534); -var parsers = __webpack_require__(536); +var compilers = __webpack_require__(503); +var parsers = __webpack_require__(505); /** * Module dependencies */ -var debug = __webpack_require__(490)('expand-brackets'); +var debug = __webpack_require__(458)('expand-brackets'); var extend = __webpack_require__(394); var Snapdragon = __webpack_require__(424); var toRegex = __webpack_require__(385); @@ -53839,13 +51154,13 @@ module.exports = brackets; /***/ }), -/* 534 */ +/* 503 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(535); +var posix = __webpack_require__(504); module.exports = function(brackets) { brackets.compiler @@ -53933,7 +51248,7 @@ module.exports = function(brackets) { /***/ }), -/* 535 */ +/* 504 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53962,14 +51277,14 @@ module.exports = { /***/ }), -/* 536 */ +/* 505 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(537); -var define = __webpack_require__(538); +var utils = __webpack_require__(506); +var define = __webpack_require__(386); /** * Text regex @@ -53988,858 +51303,256 @@ function parsers(brackets) { brackets.parser .capture('escape', function() { - if (this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(/^\\(.)/); - if (!m) return; - - return pos({ - type: 'escape', - val: m[0] - }); - }) - - /** - * Text parser - */ - - .capture('text', function() { - if (this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(not); - if (!m || !m[0]) return; - - return pos({ - type: 'text', - val: m[0] - }); - }) - - /** - * POSIX character classes: "[[:alpha:][:digits:]]" - */ - - .capture('posix', function() { - var pos = this.position(); - var m = this.match(/^\[:(.*?):\](?=.*\])/); - if (!m) return; - - var inside = this.isInside('bracket'); - if (inside) { - brackets.posix++; - } - - return pos({ - type: 'posix', - insideBracket: inside, - inner: m[1], - val: m[0] - }); - }) - - /** - * Bracket (noop) - */ - - .capture('bracket', function() {}) - - /** - * Open: '[' - */ - - .capture('bracket.open', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^\[(?=.*\])/); - if (!m) return; - - var prev = this.prev(); - var last = utils.last(prev.nodes); - - if (parsed.slice(-1) === '\\' && !this.isInside('bracket')) { - last.val = last.val.slice(0, last.val.length - 1); - return pos({ - type: 'escape', - val: m[0] - }); - } - - var open = pos({ - type: 'bracket.open', - val: m[0] - }); - - if (last.type === 'bracket.open' || this.isInside('bracket')) { - open.val = '\\' + open.val; - open.type = 'bracket.inner'; - open.escaped = true; - return open; - } - - var node = pos({ - type: 'bracket', - nodes: [open] - }); - - define(node, 'parent', prev); - define(open, 'parent', node); - this.push('bracket', node); - prev.nodes.push(node); - }) - - /** - * Bracket text - */ - - .capture('bracket.inner', function() { - if (!this.isInside('bracket')) return; - var pos = this.position(); - var m = this.match(not); - if (!m || !m[0]) return; - - var next = this.input.charAt(0); - var val = m[0]; - - var node = pos({ - type: 'bracket.inner', - val: val - }); - - if (val === '\\\\') { - return node; - } - - var first = val.charAt(0); - var last = val.slice(-1); - - if (first === '!') { - val = '^' + val.slice(1); - } - - if (last === '\\' || (val === '^' && next === ']')) { - val += this.input[0]; - this.consume(1); - } - - node.val = val; - return node; - }) - - /** - * Close: ']' - */ - - .capture('bracket.close', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(/^\]/); - if (!m) return; - - var prev = this.prev(); - var last = utils.last(prev.nodes); - - if (parsed.slice(-1) === '\\' && !this.isInside('bracket')) { - last.val = last.val.slice(0, last.val.length - 1); - - return pos({ - type: 'escape', - val: m[0] - }); - } - - var node = pos({ - type: 'bracket.close', - rest: this.input, - val: m[0] - }); - - if (last.type === 'bracket.open') { - node.type = 'bracket.inner'; - node.escaped = true; - return node; - } - - var bracket = this.pop('bracket'); - if (!this.isType(bracket, 'bracket')) { - if (this.options.strict) { - throw new Error('missing opening "["'); - } - node.type = 'bracket.inner'; - node.escaped = true; - return node; - } - - bracket.nodes.push(node); - define(node, 'parent', bracket); - }); -} - -/** - * Brackets parsers - */ - -module.exports = parsers; - -/** - * Expose text regex - */ - -module.exports.TEXT_REGEX = TEXT_REGEX; - - -/***/ }), -/* 537 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var toRegex = __webpack_require__(385); -var regexNot = __webpack_require__(396); -var cached; - -/** - * Get the last element from `array` - * @param {Array} `array` - * @return {*} - */ - -exports.last = function(arr) { - return arr[arr.length - 1]; -}; - -/** - * Create and cache regex to use for text nodes - */ - -exports.createRegex = function(pattern, include) { - if (cached) return cached; - var opts = {contains: true, strictClose: false}; - var not = regexNot.create(pattern, opts); - var re; - - if (typeof include === 'string') { - re = toRegex('^(?:' + include + '|' + not + ')', opts); - } else { - re = toRegex(not, opts); - } - - return (cached = re); -}; - - -/***/ }), -/* 538 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isDescriptor = __webpack_require__(539); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } - - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; - - -/***/ }), -/* 539 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(540); -var isAccessor = __webpack_require__(541); -var isData = __webpack_require__(543); - -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; - } - if ('get' in obj) { - return isAccessor(obj, key); - } - return isData(obj, key); -}; - - -/***/ }), -/* 540 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - var type = typeof val; - - // primitivies - if (type === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (type === 'string' || val instanceof String) { - return 'string'; - } - if (type === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (type === 'function' || val instanceof Function) { - if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { - return 'generatorfunction'; - } - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - if (type === '[object Map Iterator]') { - return 'mapiterator'; - } - if (type === '[object Set Iterator]') { - return 'setiterator'; - } - if (type === '[object String Iterator]') { - return 'stringiterator'; - } - if (type === '[object Array Iterator]') { - return 'arrayiterator'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - return val.constructor - && typeof val.constructor.isBuffer === 'function' - && val.constructor.isBuffer(val); -} - - -/***/ }), -/* 541 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-accessor-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(542); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; - -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (typeOf(obj) !== 'object') { - return false; - } - - if (has(obj, 'value') || has(obj, 'writable')) { - return false; - } + if (this.isInside('bracket')) return; + var pos = this.position(); + var m = this.match(/^\\(.)/); + if (!m) return; - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; - } + return pos({ + type: 'escape', + val: m[0] + }); + }) - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } + /** + * Text parser + */ - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; - } + .capture('text', function() { + if (this.isInside('bracket')) return; + var pos = this.position(); + var m = this.match(not); + if (!m || !m[0]) return; - if (typeOf(obj[key]) === accessor[key]) { - continue; - } + return pos({ + type: 'text', + val: m[0] + }); + }) - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -} + /** + * POSIX character classes: "[[:alpha:][:digits:]]" + */ -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} + .capture('posix', function() { + var pos = this.position(); + var m = this.match(/^\[:(.*?):\](?=.*\])/); + if (!m) return; -/** - * Expose `isAccessorDescriptor` - */ + var inside = this.isInside('bracket'); + if (inside) { + brackets.posix++; + } -module.exports = isAccessorDescriptor; + return pos({ + type: 'posix', + insideBracket: inside, + inner: m[1], + val: m[0] + }); + }) + /** + * Bracket (noop) + */ -/***/ }), -/* 542 */ -/***/ (function(module, exports, __webpack_require__) { + .capture('bracket', function() {}) -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; + /** + * Open: '[' + */ -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ + .capture('bracket.open', function() { + var parsed = this.parsed; + var pos = this.position(); + var m = this.match(/^\[(?=.*\])/); + if (!m) return; -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } + var prev = this.prev(); + var last = utils.last(prev.nodes); - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } + if (parsed.slice(-1) === '\\' && !this.isInside('bracket')) { + last.val = last.val.slice(0, last.val.length - 1); + return pos({ + type: 'escape', + val: m[0] + }); + } - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } + var open = pos({ + type: 'bracket.open', + val: m[0] + }); - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } + if (last.type === 'bracket.open' || this.isInside('bracket')) { + open.val = '\\' + open.val; + open.type = 'bracket.inner'; + open.escaped = true; + return open; + } - // other objects - var type = toString.call(val); + var node = pos({ + type: 'bracket', + nodes: [open] + }); - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } + define(node, 'parent', prev); + define(open, 'parent', node); + this.push('bracket', node); + prev.nodes.push(node); + }) - // buffer - if (isBuffer(val)) { - return 'buffer'; - } + /** + * Bracket text + */ - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } + .capture('bracket.inner', function() { + if (!this.isInside('bracket')) return; + var pos = this.position(); + var m = this.match(not); + if (!m || !m[0]) return; - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } + var next = this.input.charAt(0); + var val = m[0]; - // must be a plain object - return 'object'; -}; + var node = pos({ + type: 'bracket.inner', + val: val + }); + if (val === '\\\\') { + return node; + } -/***/ }), -/* 543 */ -/***/ (function(module, exports, __webpack_require__) { + var first = val.charAt(0); + var last = val.slice(-1); -"use strict"; -/*! - * is-data-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ + if (first === '!') { + val = '^' + val.slice(1); + } + if (last === '\\' || (val === '^' && next === ']')) { + val += this.input[0]; + this.consume(1); + } + node.val = val; + return node; + }) -var typeOf = __webpack_require__(544); + /** + * Close: ']' + */ -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' -}; + .capture('bracket.close', function() { + var parsed = this.parsed; + var pos = this.position(); + var m = this.match(/^\]/); + if (!m) return; -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } + var prev = this.prev(); + var last = utils.last(prev.nodes); - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } + if (parsed.slice(-1) === '\\' && !this.isInside('bracket')) { + last.val = last.val.slice(0, last.val.length - 1); - if (!('value' in obj) && !('writable' in obj)) { - return false; - } + return pos({ + type: 'escape', + val: m[0] + }); + } - for (var key in obj) { - if (key === 'value') continue; + var node = pos({ + type: 'bracket.close', + rest: this.input, + val: m[0] + }); - if (!data.hasOwnProperty(key)) { - continue; - } + if (last.type === 'bracket.open') { + node.type = 'bracket.inner'; + node.escaped = true; + return node; + } - if (typeOf(obj[key]) === data[key]) { - continue; - } + var bracket = this.pop('bracket'); + if (!this.isType(bracket, 'bracket')) { + if (this.options.strict) { + throw new Error('missing opening "["'); + } + node.type = 'bracket.inner'; + node.escaped = true; + return node; + } - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; + bracket.nodes.push(node); + define(node, 'parent', bracket); + }); } /** - * Expose `isDataDescriptor` + * Brackets parsers */ -module.exports = isDataDescriptor; - - -/***/ }), -/* 544 */ -/***/ (function(module, exports, __webpack_require__) { - -var isBuffer = __webpack_require__(391); -var toString = Object.prototype.toString; +module.exports = parsers; /** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type + * Expose text regex */ -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } +module.exports.TEXT_REGEX = TEXT_REGEX; - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } +/***/ }), +/* 506 */ +/***/ (function(module, exports, __webpack_require__) { - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } +"use strict"; - // other objects - var type = toString.call(val); - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } +var toRegex = __webpack_require__(385); +var regexNot = __webpack_require__(396); +var cached; - // buffer - if (isBuffer(val)) { - return 'buffer'; - } +/** + * Get the last element from `array` + * @param {Array} `array` + * @return {*} + */ - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } +exports.last = function(arr) { + return arr[arr.length - 1]; +}; - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; +/** + * Create and cache regex to use for text nodes + */ + +exports.createRegex = function(pattern, include) { + if (cached) return cached; + var opts = {contains: true, strictClose: false}; + var not = regexNot.create(pattern, opts); + var re; + + if (typeof include === 'string') { + re = toRegex('^(?:' + include + '|' + not + ')', opts); + } else { + re = toRegex(not, opts); } - // must be a plain object - return 'object'; + return (cached = re); }; /***/ }), -/* 545 */ +/* 507 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(533); -var define = __webpack_require__(398); -var utils = __webpack_require__(546); +var brackets = __webpack_require__(502); +var define = __webpack_require__(496); +var utils = __webpack_require__(508); /** * Characters to use in text regex (we want to "not" match @@ -54994,14 +51707,14 @@ module.exports = parsers; /***/ }), -/* 546 */ +/* 508 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var regex = __webpack_require__(396); -var Cache = __webpack_require__(526); +var Cache = __webpack_require__(494); /** * Utils @@ -55070,7 +51783,7 @@ utils.createRegex = function(str) { /***/ }), -/* 547 */ +/* 509 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55081,15 +51794,15 @@ utils.createRegex = function(str) { */ var Snapdragon = __webpack_require__(424); -var define = __webpack_require__(398); +var define = __webpack_require__(496); var extend = __webpack_require__(394); /** * Local dependencies */ -var compilers = __webpack_require__(532); -var parsers = __webpack_require__(545); +var compilers = __webpack_require__(501); +var parsers = __webpack_require__(507); /** * Customize Snapdragon parser and renderer @@ -55155,14 +51868,14 @@ module.exports = Extglob; /***/ }), -/* 548 */ +/* 510 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(531); -var nanomatch = __webpack_require__(521); +var extglob = __webpack_require__(500); +var nanomatch = __webpack_require__(489); var regexNot = __webpack_require__(396); var toRegex = __webpack_require__(385); var not; @@ -55245,14 +51958,14 @@ function textRegex(pattern) { /***/ }), -/* 549 */ +/* 511 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(526))(); +module.exports = new (__webpack_require__(494))(); /***/ }), -/* 550 */ +/* 512 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55266,11 +51979,11 @@ var path = __webpack_require__(16); */ var Snapdragon = __webpack_require__(424); -utils.define = __webpack_require__(398); -utils.diff = __webpack_require__(528); +utils.define = __webpack_require__(496); +utils.diff = __webpack_require__(497); utils.extend = __webpack_require__(394); -utils.pick = __webpack_require__(529); -utils.typeOf = __webpack_require__(551); +utils.pick = __webpack_require__(498); +utils.typeOf = __webpack_require__(513); utils.unique = __webpack_require__(397); /** @@ -55568,7 +52281,7 @@ utils.unixify = function(options) { /***/ }), -/* 551 */ +/* 513 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -55703,7 +52416,7 @@ function isBuffer(val) { /***/ }), -/* 552 */ +/* 514 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55719,8 +52432,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(553); -var reader_1 = __webpack_require__(566); +var readdir = __webpack_require__(515); +var reader_1 = __webpack_require__(528); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -55756,15 +52469,15 @@ exports.default = ReaderAsync; /***/ }), -/* 553 */ +/* 515 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(554); -const readdirAsync = __webpack_require__(562); -const readdirStream = __webpack_require__(565); +const readdirSync = __webpack_require__(516); +const readdirAsync = __webpack_require__(524); +const readdirStream = __webpack_require__(527); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -55848,7 +52561,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 554 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55856,11 +52569,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(555); +const DirectoryReader = __webpack_require__(517); let syncFacade = { - fs: __webpack_require__(560), - forEach: __webpack_require__(561), + fs: __webpack_require__(522), + forEach: __webpack_require__(523), sync: true }; @@ -55889,7 +52602,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 555 */ +/* 517 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55898,9 +52611,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(28).Readable; const EventEmitter = __webpack_require__(45).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(556); -const stat = __webpack_require__(558); -const call = __webpack_require__(559); +const normalizeOptions = __webpack_require__(518); +const stat = __webpack_require__(520); +const call = __webpack_require__(521); /** * Asynchronously reads the contents of a directory and streams the results @@ -56276,14 +52989,14 @@ module.exports = DirectoryReader; /***/ }), -/* 556 */ +/* 518 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(557); +const globToRegExp = __webpack_require__(519); module.exports = normalizeOptions; @@ -56460,7 +53173,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 557 */ +/* 519 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -56597,13 +53310,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 558 */ +/* 520 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(559); +const call = __webpack_require__(521); module.exports = stat; @@ -56678,7 +53391,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 559 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56739,14 +53452,14 @@ function callOnce (fn) { /***/ }), -/* 560 */ +/* 522 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(559); +const call = __webpack_require__(521); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -56810,7 +53523,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 561 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56839,7 +53552,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 562 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56847,12 +53560,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(563); -const DirectoryReader = __webpack_require__(555); +const maybe = __webpack_require__(525); +const DirectoryReader = __webpack_require__(517); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(564), + forEach: __webpack_require__(526), async: true }; @@ -56894,7 +53607,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 563 */ +/* 525 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56921,7 +53634,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 564 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56957,7 +53670,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 565 */ +/* 527 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56965,11 +53678,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(555); +const DirectoryReader = __webpack_require__(517); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(564), + forEach: __webpack_require__(526), async: true }; @@ -56989,15 +53702,15 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 566 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(567); -var entry_1 = __webpack_require__(570); +var deep_1 = __webpack_require__(529); +var entry_1 = __webpack_require__(532); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -57063,14 +53776,14 @@ exports.default = Reader; /***/ }), -/* 567 */ +/* 529 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var arrayUtils = __webpack_require__(568); -var pathUtils = __webpack_require__(569); +var arrayUtils = __webpack_require__(530); +var pathUtils = __webpack_require__(531); var patternUtils = __webpack_require__(378); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { @@ -57146,7 +53859,7 @@ exports.default = DeepFilter; /***/ }), -/* 568 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57169,7 +53882,7 @@ exports.max = max; /***/ }), -/* 569 */ +/* 531 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57187,7 +53900,7 @@ exports.isDotDirectory = isDotDirectory; /***/ }), -/* 570 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57265,7 +53978,7 @@ exports.default = DeepFilter; /***/ }), -/* 571 */ +/* 533 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57282,8 +53995,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(28); -var readdir = __webpack_require__(553); -var reader_1 = __webpack_require__(566); +var readdir = __webpack_require__(515); +var reader_1 = __webpack_require__(528); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -57326,7 +54039,7 @@ exports.default = ReaderStream; /***/ }), -/* 572 */ +/* 534 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57342,8 +54055,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(553); -var reader_1 = __webpack_require__(566); +var readdir = __webpack_require__(515); +var reader_1 = __webpack_require__(528); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -57378,7 +54091,7 @@ exports.default = ReaderSync; /***/ }), -/* 573 */ +/* 535 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57433,7 +54146,7 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 574 */ +/* 536 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57441,9 +54154,9 @@ module.exports.sync = (input, opts) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const fastGlob = __webpack_require__(372); -const gitIgnore = __webpack_require__(575); +const gitIgnore = __webpack_require__(537); const pify = __webpack_require__(62); -const slash = __webpack_require__(576); +const slash = __webpack_require__(538); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -57535,7 +54248,7 @@ module.exports.sync = o => { /***/ }), -/* 575 */ +/* 537 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57967,7 +54680,7 @@ typeof process !== 'undefined' && (process.env && process.env.IGNORE_TEST_WIN32 /***/ }), -/* 576 */ +/* 538 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57985,17 +54698,17 @@ module.exports = function (str) { /***/ }), -/* 577 */ +/* 539 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const fsConstants = __webpack_require__(23).constants; -const {Buffer} = __webpack_require__(578); -const CpFileError = __webpack_require__(580); -const fs = __webpack_require__(582); -const ProgressEmitter = __webpack_require__(583); +const {Buffer} = __webpack_require__(540); +const CpFileError = __webpack_require__(542); +const fs = __webpack_require__(544); +const ProgressEmitter = __webpack_require__(545); module.exports = (src, dest, opts) => { if (!src || !dest) { @@ -58145,11 +54858,11 @@ module.exports.sync = (src, dest, opts) => { /***/ }), -/* 578 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { /* eslint-disable node/no-deprecated-api */ -var buffer = __webpack_require__(579) +var buffer = __webpack_require__(541) var Buffer = buffer.Buffer // alternative to using Object.keys for old browsers @@ -58213,18 +54926,18 @@ SafeBuffer.allocUnsafeSlow = function (size) { /***/ }), -/* 579 */ +/* 541 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 580 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(581); +const NestedError = __webpack_require__(543); class CpFileError extends NestedError { constructor(message, nested) { @@ -58238,7 +54951,7 @@ module.exports = CpFileError; /***/ }), -/* 581 */ +/* 543 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(43); @@ -58292,7 +55005,7 @@ module.exports = NestedError; /***/ }), -/* 582 */ +/* 544 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58300,7 +55013,7 @@ module.exports = NestedError; const fs = __webpack_require__(22); const makeDir = __webpack_require__(90); const pify = __webpack_require__(62); -const CpFileError = __webpack_require__(580); +const CpFileError = __webpack_require__(542); const fsP = pify(fs); @@ -58445,7 +55158,7 @@ if (fs.copyFileSync) { /***/ }), -/* 583 */ +/* 545 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58486,12 +55199,12 @@ module.exports = ProgressEmitter; /***/ }), -/* 584 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(581); +const NestedError = __webpack_require__(543); class CpyError extends NestedError { constructor(message, nested) { @@ -58505,7 +55218,7 @@ module.exports = CpyError; /***/ }), -/* 585 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; From 6cbecd2fe82df4f928d7942fc6b6e0b3e1622357 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 22 Mar 2019 16:12:07 -0700 Subject: [PATCH 15/96] remove unused system-loader implementation (#33747) This code was added when we were first experimenting with the new platform in the UI, isn't being used by anything, and is very similar to the implementation we ended up going with in https://github.com/elastic/kibana/blob/master/src/core/server/plugins/plugin.ts and https://github.com/elastic/kibana/blob/master/src/core/server/plugins/plugins_system.ts --- packages/kbn-system-loader/package.json | 11 - .../src/__snapshots__/system.test.ts.snap | 5 - .../__snapshots__/system_loader.test.ts.snap | 5 - .../topological_sort.test.ts.snap | 3 - packages/kbn-system-loader/src/index.ts | 22 - .../kbn-system-loader/src/sorted_systems.ts | 41 -- packages/kbn-system-loader/src/system.test.ts | 101 ---- packages/kbn-system-loader/src/system.ts | 90 ---- .../src/system_loader.test.ts | 499 ------------------ .../kbn-system-loader/src/system_loader.ts | 102 ---- .../kbn-system-loader/src/system_types.ts | 51 -- .../src/topological_sort.test.ts | 55 -- .../kbn-system-loader/src/topological_sort.ts | 78 --- packages/kbn-system-loader/tsconfig.json | 10 - 14 files changed, 1073 deletions(-) delete mode 100644 packages/kbn-system-loader/package.json delete mode 100644 packages/kbn-system-loader/src/__snapshots__/system.test.ts.snap delete mode 100644 packages/kbn-system-loader/src/__snapshots__/system_loader.test.ts.snap delete mode 100644 packages/kbn-system-loader/src/__snapshots__/topological_sort.test.ts.snap delete mode 100644 packages/kbn-system-loader/src/index.ts delete mode 100644 packages/kbn-system-loader/src/sorted_systems.ts delete mode 100644 packages/kbn-system-loader/src/system.test.ts delete mode 100644 packages/kbn-system-loader/src/system.ts delete mode 100644 packages/kbn-system-loader/src/system_loader.test.ts delete mode 100644 packages/kbn-system-loader/src/system_loader.ts delete mode 100644 packages/kbn-system-loader/src/system_types.ts delete mode 100644 packages/kbn-system-loader/src/topological_sort.test.ts delete mode 100644 packages/kbn-system-loader/src/topological_sort.ts delete mode 100644 packages/kbn-system-loader/tsconfig.json diff --git a/packages/kbn-system-loader/package.json b/packages/kbn-system-loader/package.json deleted file mode 100644 index 6e6c0eeaeac5c..0000000000000 --- a/packages/kbn-system-loader/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "@kbn/system-loader", - "version": "1.0.0", - "license": "Apache-2.0", - "private": true, - "main": "src/index.js", - "typings": "src/index.d.ts", - "dependencies": { - "tslib": "^1.9.3" - } -} diff --git a/packages/kbn-system-loader/src/__snapshots__/system.test.ts.snap b/packages/kbn-system-loader/src/__snapshots__/system.test.ts.snap deleted file mode 100644 index 4ac79d3a6e863..0000000000000 --- a/packages/kbn-system-loader/src/__snapshots__/system.test.ts.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`throws if start returns a promise 1`] = `"A promise was returned when starting [foo], but systems must start synchronously and return either return undefined or the contract they expose to other systems."`; - -exports[`throws if stop returns a promise 1`] = `"A promise was returned when stopping [foo], but systems must stop synchronously."`; diff --git a/packages/kbn-system-loader/src/__snapshots__/system_loader.test.ts.snap b/packages/kbn-system-loader/src/__snapshots__/system_loader.test.ts.snap deleted file mode 100644 index ef7fdb20c09e9..0000000000000 --- a/packages/kbn-system-loader/src/__snapshots__/system_loader.test.ts.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`throws if adding that has the same name as a system that's already added 1`] = `"a system named [foo] has already been added"`; - -exports[`throws if starting a system that depends on a system that's not present 1`] = `"System [foo] depends on [does-not-exist], which is not present"`; diff --git a/packages/kbn-system-loader/src/__snapshots__/topological_sort.test.ts.snap b/packages/kbn-system-loader/src/__snapshots__/topological_sort.test.ts.snap deleted file mode 100644 index a2041c4b6182f..0000000000000 --- a/packages/kbn-system-loader/src/__snapshots__/topological_sort.test.ts.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`throws if ordering does not succeed 1`] = `"Topological ordering did not complete, these edges could not be ordered: [[\\"a\\",[\\"b\\"]],[\\"b\\",[\\"c\\"]],[\\"c\\",[\\"a\\"]],[\\"f\\",[\\"g\\"]]]"`; diff --git a/packages/kbn-system-loader/src/index.ts b/packages/kbn-system-loader/src/index.ts deleted file mode 100644 index d7fcc9e209e31..0000000000000 --- a/packages/kbn-system-loader/src/index.ts +++ /dev/null @@ -1,22 +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 { SystemLoader } from './system_loader'; -export { System } from './system'; -export { KibanaSystem } from './system_types'; diff --git a/packages/kbn-system-loader/src/sorted_systems.ts b/packages/kbn-system-loader/src/sorted_systems.ts deleted file mode 100644 index 85dcc64ed9654..0000000000000 --- a/packages/kbn-system-loader/src/sorted_systems.ts +++ /dev/null @@ -1,41 +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 { System } from './system'; -import { SystemName } from './system_types'; -import { topologicalSort } from './topological_sort'; - -// We need this helper for the types to be correct when creating Map -// (otherwise it assumes an array of A|B instead of a tuple [A,B]) -const toTuple = (a: A, b: B): [A, B] => [a, b]; - -function toSortable(systems: Map>) { - const dependenciesBySystem = [...systems.entries()].map(([name, system]) => - toTuple(name, system.dependencies || []) - ); - return new Map(dependenciesBySystem); -} - -/** - * Sorts systems in topological order based on dependencies - */ -export function getSortedSystemNames(systems: Map>) { - const sorted = topologicalSort(toSortable(systems)); - return [...sorted]; -} diff --git a/packages/kbn-system-loader/src/system.test.ts b/packages/kbn-system-loader/src/system.test.ts deleted file mode 100644 index d4267f82e85ae..0000000000000 --- a/packages/kbn-system-loader/src/system.test.ts +++ /dev/null @@ -1,101 +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. - */ - -/* tslint:disable max-classes-per-file */ - -import { System } from './system'; -import { KibanaSystem } from './system_types'; - -test('can get exposed values after starting', () => { - interface ICoreType { - bar: string; - } - interface IDepsType { - quux: string; - } - interface IExposedType { - core: ICoreType; - deps: IDepsType; - } - - class FooSystem extends KibanaSystem { - public start() { - return { - core: this.kibana, - deps: this.deps, - }; - } - } - - const system = new System('foo', { - implementation: FooSystem, - }); - - system.start( - { - bar: 'bar', - }, - { - quux: 'quux', - } - ); - - expect(system.getExposedValues()).toEqual({ - core: { bar: 'bar' }, - deps: { quux: 'quux' }, - }); -}); - -test('throws if start returns a promise', () => { - class FooSystem extends KibanaSystem { - public async start() { - return 'foo'; - } - } - - const system = new System('foo', { - implementation: FooSystem, - }); - - expect(() => { - system.start({}, {}); - }).toThrowErrorMatchingSnapshot(); -}); - -test('throws if stop returns a promise', () => { - class FooSystem extends KibanaSystem { - public start() { - // noop - } - - public async stop() { - return 'stop'; - } - } - - const system = new System('foo', { - implementation: FooSystem, - }); - - system.start({}, {}); - - expect(() => { - system.stop(); - }).toThrowErrorMatchingSnapshot(); -}); diff --git a/packages/kbn-system-loader/src/system.ts b/packages/kbn-system-loader/src/system.ts deleted file mode 100644 index 7f42c073a97de..0000000000000 --- a/packages/kbn-system-loader/src/system.ts +++ /dev/null @@ -1,90 +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 { - KibanaSystem, - KibanaSystemClassStatic, - SystemMetadata, - SystemName, - SystemsType, -} from './system_types'; - -function isPromise(obj: any) { - return obj != null && typeof obj === 'object' && typeof obj.then === 'function'; -} - -export class System { - public readonly name: SystemName; - public readonly dependencies: SystemName[]; - public readonly metadata?: M; - - private readonly systemClass: KibanaSystemClassStatic; - private systemInstance?: KibanaSystem; - private exposedValues?: E; - - constructor( - name: SystemName, - config: { - metadata?: M; - dependencies?: SystemName[]; - implementation: KibanaSystemClassStatic; - } - ) { - this.name = name; - this.dependencies = config.dependencies || []; - this.metadata = config.metadata; - this.systemClass = config.implementation; - } - - public getExposedValues(): E { - if (this.systemInstance === undefined) { - throw new Error('trying to get the exposed value of a system that is NOT running'); - } - - return this.exposedValues!; - } - - public start(kibanaValues: C, dependenciesValues: D) { - this.systemInstance = new this.systemClass(kibanaValues, dependenciesValues); - const exposedValues = this.systemInstance.start(); - - if (isPromise(exposedValues)) { - throw new Error( - `A promise was returned when starting [${ - this.name - }], but systems must start synchronously and return either return undefined or the contract they expose to other systems.` - ); - } - - this.exposedValues = exposedValues === undefined ? ({} as E) : exposedValues; - } - - public stop() { - const stoppedResponse = this.systemInstance && this.systemInstance.stop(); - - this.exposedValues = undefined; - this.systemInstance = undefined; - - if (isPromise(stoppedResponse)) { - throw new Error( - `A promise was returned when stopping [${this.name}], but systems must stop synchronously.` - ); - } - } -} diff --git a/packages/kbn-system-loader/src/system_loader.test.ts b/packages/kbn-system-loader/src/system_loader.test.ts deleted file mode 100644 index c6d2beff24f34..0000000000000 --- a/packages/kbn-system-loader/src/system_loader.test.ts +++ /dev/null @@ -1,499 +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. - */ - -/* tslint:disable max-classes-per-file */ - -import { System } from './system'; -import { KibanaSystemApiFactory, SystemLoader } from './system_loader'; -import { KibanaSystem } from './system_types'; - -// To make types simpler in the tests -type CoreType = void; -const createCoreValues = () => { - // noop -}; - -test('starts system with core api', () => { - expect.assertions(1); - - interface IKibanaCoreApi { - fromCore: boolean; - name: string; - } - interface IMetadata { - configPath?: string; - } - - class FooSystem extends KibanaSystem { - public start() { - expect(this.kibana).toEqual({ - fromCore: true, - metadata: { - configPath: 'config.path.foo', - }, - name: 'foo', - }); - } - } - - const foo = new System('foo', { - implementation: FooSystem, - metadata: { - configPath: 'config.path.foo', - }, - }); - - const createSystemApi: KibanaSystemApiFactory = (name, metadata) => { - return { - fromCore: true, - metadata, - name, - }; - }; - - const systems = new SystemLoader(createSystemApi); - systems.addSystem(foo); - - systems.startSystems(); -}); - -test('system can expose a value', () => { - expect.assertions(1); - - interface IFoo { - foo: { - value: string; - }; - } - - class FooSystem extends KibanaSystem { - public start() { - return { - value: 'my-value', - }; - } - } - - class BarSystem extends KibanaSystem { - public start() { - expect(this.deps.foo).toEqual({ value: 'my-value' }); - } - } - - const foo = new System('foo', { - implementation: FooSystem, - }); - - const bar = new System('bar', { - dependencies: ['foo'], - implementation: BarSystem, - }); - - const systems = new SystemLoader(createCoreValues); - systems.addSystem(foo); - systems.addSystem(bar); - systems.startSystems(); -}); - -test('system can expose a function', () => { - expect.assertions(2); - - interface IFoo { - foo: { - fn: (val: string) => string; - }; - } - - class FooSystem extends KibanaSystem { - public start(): IFoo['foo'] { - return { - fn: val => `test-${val}`, - }; - } - } - - class BarSystem extends KibanaSystem { - public start() { - expect(this.deps.foo).toBeDefined(); - expect(this.deps.foo.fn('some-value')).toBe('test-some-value'); - } - } - - const foo = new System('foo', { - implementation: FooSystem, - }); - - const bar = new System('bar', { - dependencies: ['foo'], - implementation: BarSystem, - }); - - const systems = new SystemLoader(createCoreValues); - systems.addSystem(foo); - systems.addSystem(bar); - systems.startSystems(); -}); - -test('can expose value with same name across multiple systems', () => { - expect.assertions(2); - - interface IFoo { - foo: { - value: string; - }; - } - - interface IBar { - bar: { - value: string; - }; - } - - class FooSystem extends KibanaSystem { - public start(): IFoo['foo'] { - return { - value: 'value-foo', - }; - } - } - - class BarSystem extends KibanaSystem { - public start(): IBar['bar'] { - return { - value: 'value-bar', - }; - } - } - - class QuuxSystem extends KibanaSystem { - public start() { - expect(this.deps.foo).toEqual({ value: 'value-foo' }); - expect(this.deps.bar).toEqual({ value: 'value-bar' }); - } - } - - const foo = new System('foo', { - implementation: FooSystem, - }); - - const bar = new System('bar', { - implementation: BarSystem, - }); - - const quux = new System('quux', { - dependencies: ['foo', 'bar'], - implementation: QuuxSystem, - }); - - const systems = new SystemLoader(createCoreValues); - systems.addSystem(foo); - systems.addSystem(bar); - systems.addSystem(quux); - systems.startSystems(); -}); - -test('receives values from dependencies but not transitive dependencies', () => { - expect.assertions(3); - - interface IGrandchild { - grandchild: { - value: string; - }; - } - - interface IChild { - child: { - value: string; - }; - } - - class GrandchildSystem extends KibanaSystem { - public start() { - return { - value: 'grandchild', - }; - } - } - - class ChildSystem extends KibanaSystem { - public start() { - expect(this.deps.grandchild).toEqual({ value: 'grandchild' }); - - return { - value: 'child', - }; - } - } - - class ParentSystem extends KibanaSystem { - public start() { - expect(this.deps.child).toEqual({ value: 'child' }); - expect(this.deps.grandchild).toBeUndefined(); - } - } - - const grandchild = new System('grandchild', { - implementation: GrandchildSystem, - }); - - const child = new System('child', { - dependencies: ['grandchild'], - implementation: ChildSystem, - }); - - const parent = new System('parent', { - dependencies: ['child'], - implementation: ParentSystem, - }); - - const systems = new SystemLoader(createCoreValues); - systems.addSystem(grandchild); - systems.addSystem(child); - systems.addSystem(parent); - systems.startSystems(); -}); - -test('keeps reference on registered value', () => { - expect.assertions(1); - - interface IChild { - child: { - value: {}; - }; - } - - const myRef = {}; - - class ChildSystem extends KibanaSystem { - public start() { - return { - value: myRef, - }; - } - } - - class ParentSystem extends KibanaSystem { - public start() { - expect(this.deps.child.value).toBe(myRef); - } - } - - const child = new System('child', { - implementation: ChildSystem, - }); - - const parent = new System('parent', { - dependencies: ['child'], - implementation: ParentSystem, - }); - - const systems = new SystemLoader(createCoreValues); - systems.addSystem(child); - systems.addSystem(parent); - systems.startSystems(); -}); - -test('can register multiple values in single system', () => { - expect.assertions(1); - - interface IChild { - child: { - value1: number; - value2: number; - }; - } - - class ChildSystem extends KibanaSystem { - public start() { - return { - value1: 1, - value2: 2, - }; - } - } - - class ParentSystem extends KibanaSystem { - public start() { - expect(this.deps.child).toEqual({ - value1: 1, - value2: 2, - }); - } - } - - const child = new System('child', { - implementation: ChildSystem, - }); - - const parent = new System('parent', { - dependencies: ['child'], - implementation: ParentSystem, - }); - - const systems = new SystemLoader(createCoreValues); - systems.addSystem(child); - systems.addSystem(parent); - systems.startSystems(); -}); - -test("throws if starting a system that depends on a system that's not present", () => { - class FooSystem extends KibanaSystem { - public start() { - // noop - } - } - - const foo = new System('foo', { - dependencies: ['does-not-exist'], - implementation: FooSystem, - }); - - const systems = new SystemLoader(createCoreValues); - - systems.addSystem(foo); - - expect(() => { - systems.startSystems(); - }).toThrowErrorMatchingSnapshot(); -}); - -test("throws if adding that has the same name as a system that's already added", () => { - class FooSystem extends KibanaSystem { - public start() { - // noop - } - } - - const foo = new System('foo', { - implementation: FooSystem, - }); - - const systems = new SystemLoader(createCoreValues); - - systems.addSystem(foo); - expect(() => { - systems.addSystem(foo); - }).toThrowErrorMatchingSnapshot(); -}); - -test('stops systems in reverse order of their starting order', () => { - const events: string[] = []; - - class FooSystem extends KibanaSystem { - public start() { - events.push('start foo'); - } - public stop() { - events.push('stop foo'); - } - } - - class BarSystem extends KibanaSystem { - public start() { - events.push('start bar'); - } - public stop() { - events.push('stop bar'); - } - } - - const foo = new System('foo', { - implementation: FooSystem, - }); - const bar = new System('bar', { - implementation: BarSystem, - }); - - const systems = new SystemLoader(createCoreValues); - - systems.addSystem(foo); - systems.addSystem(bar); - - systems.startSystems(); - systems.stopSystems(); - - expect(events).toEqual(['start bar', 'start foo', 'stop foo', 'stop bar']); -}); - -test('can add systems before adding its dependencies', () => { - expect.assertions(1); - - interface IFoo { - foo: string; - } - - class FooSystem extends KibanaSystem { - public start() { - return 'value'; - } - } - - class BarSystem extends KibanaSystem { - public start() { - expect(this.deps.foo).toBe('value'); - } - } - - const foo = new System('foo', { - implementation: FooSystem, - }); - - const bar = new System('bar', { - dependencies: ['foo'], - implementation: BarSystem, - }); - - const systems = new SystemLoader(createCoreValues); - // `bar` depends on `foo`, but we add it first - systems.addSystem(bar); - systems.addSystem(foo); - systems.startSystems(); -}); - -test('can add multiple system specs at the same time', () => { - expect.assertions(1); - - const spy = jest.fn(); - - class FooSystem extends KibanaSystem { - public start() { - spy(); - } - } - - class BarSystem extends KibanaSystem { - public start() { - spy(); - } - } - - const foo = new System('foo', { - implementation: FooSystem, - }); - - const bar = new System('bar', { - implementation: BarSystem, - }); - - const systems = new SystemLoader(createCoreValues); - systems.addSystems([foo, bar]); - systems.startSystems(); - - expect(spy).toHaveBeenCalledTimes(2); -}); diff --git a/packages/kbn-system-loader/src/system_loader.ts b/packages/kbn-system-loader/src/system_loader.ts deleted file mode 100644 index b3f724737be15..0000000000000 --- a/packages/kbn-system-loader/src/system_loader.ts +++ /dev/null @@ -1,102 +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 { getSortedSystemNames } from './sorted_systems'; -import { System } from './system'; -import { SystemMetadata, SystemName, SystemsType } from './system_types'; - -export type KibanaSystemApiFactory = (name: SystemName, metadata?: M) => C; - -export class SystemLoader { - private readonly systems = new Map>(); - private startedSystems: SystemName[] = []; - - constructor( - /** - * Creates the Kibana system api for each system. It is called with - * information about a system before it's started, and the return value will - * be injected into the system at startup. - */ - private readonly kibanaSystemApiFactory: KibanaSystemApiFactory - ) {} - - public addSystems(systemSpecs: Array>) { - systemSpecs.forEach(systemSpec => { - this.addSystem(systemSpec); - }); - } - - public addSystem(system: System) { - if (this.systems.has(system.name)) { - throw new Error(`a system named [${system.name}] has already been added`); - } - - this.systems.set(system.name, system); - } - - public startSystems() { - this._ensureAllSystemDependenciesCanBeResolved(); - - getSortedSystemNames(this.systems) - .map(systemName => this.systems.get(systemName)!) - .forEach(systemSpec => { - this.startSystem(systemSpec); - }); - } - - /** - * Stop all systems in the reverse order of when they were started - */ - public stopSystems() { - this.startedSystems - .map(systemName => this.systems.get(systemName)!) - .reverse() - .forEach(system => { - system.stop(); - this.systems.delete(system.name); - }); - - this.startedSystems = []; - } - - private _ensureAllSystemDependenciesCanBeResolved() { - for (const [systemName, system] of this.systems) { - for (const systemDependency of system.dependencies) { - if (!this.systems.has(systemDependency)) { - throw new Error( - `System [${systemName}] depends on [${systemDependency}], which is not present` - ); - } - } - } - } - - private startSystem(system: System) { - const dependenciesValues = {} as D; - - for (const dependency of system.dependencies) { - dependenciesValues[dependency] = this.systems.get(dependency)!.getExposedValues(); - } - - const kibanaSystemApi = this.kibanaSystemApiFactory(system.name, system.metadata); - - system.start(kibanaSystemApi, dependenciesValues); - this.startedSystems.push(system.name); - } -} diff --git a/packages/kbn-system-loader/src/system_types.ts b/packages/kbn-system-loader/src/system_types.ts deleted file mode 100644 index 3d42c12aac524..0000000000000 --- a/packages/kbn-system-loader/src/system_types.ts +++ /dev/null @@ -1,51 +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 type SystemName = string; -export interface SystemMetadata { - [key: string]: any; -} - -export interface SystemsType { - [systemName: string]: any; -} - -export abstract class KibanaSystem { - constructor(readonly kibana: C, readonly deps: D) {} - - public abstract start(): E; - - public stop() { - // default implementation of stop does nothing - } -} - -/** - * Defines the "static side" of the Kibana system class. - * - * When a class implements an interface, only the instance side of the class is - * checked, so you can't include static methods there. Because of that we have - * a separate interface for the static side, which we can use to specify that we - * want a _class_ (not an instance) that matches this interface. - * - * See https://www.typescriptlang.org/docs/handbook/interfaces.html#difference-between-the-static-and-instance-sides-of-classes - */ -export interface KibanaSystemClassStatic { - new (kibana: C, deps: D): KibanaSystem; -} diff --git a/packages/kbn-system-loader/src/topological_sort.test.ts b/packages/kbn-system-loader/src/topological_sort.test.ts deleted file mode 100644 index 8dcf8d55c8714..0000000000000 --- a/packages/kbn-system-loader/src/topological_sort.test.ts +++ /dev/null @@ -1,55 +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 { topologicalSort } from './topological_sort'; - -test('returns a topologically ordered sequence', () => { - const nodes = new Map([['a', []], ['b', ['a']], ['c', ['a', 'b']], ['d', ['a']]]); - - const sorted = topologicalSort(nodes); - - expect(sorted).toBeDefined(); - - expect([...sorted!]).toEqual(['a', 'd', 'b', 'c']); -}); - -test('handles multiple "roots" with no deps', () => { - const nodes = new Map([['a', []], ['b', []], ['c', ['a', 'b']], ['d', ['a']]]); - - const sorted = topologicalSort(nodes); - - expect(sorted).toBeDefined(); - - expect([...sorted!]).toEqual(['b', 'a', 'd', 'c']); -}); - -test('throws if ordering does not succeed', () => { - const nodes = new Map([ - ['a', ['b']], - ['b', ['c']], - ['c', ['a', 'd']], // cycles back to 'a' - ['d', []], - ['e', ['d']], - ['f', ['g']], // 'g' does not 'exist' - ]); - - expect(() => { - topologicalSort(nodes); - }).toThrowErrorMatchingSnapshot(); -}); diff --git a/packages/kbn-system-loader/src/topological_sort.ts b/packages/kbn-system-loader/src/topological_sort.ts deleted file mode 100644 index 673d12ec55740..0000000000000 --- a/packages/kbn-system-loader/src/topological_sort.ts +++ /dev/null @@ -1,78 +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. - */ - -/** - * A topological ordering is possible if and only if the graph has no directed - * cycles, that is, if it is a directed acyclic graph (DAG). If the input cannot - * be ordered an error is thrown. - * - * Uses Kahn's Algorithm to sort the graph. - * - * @param graph A directed acyclic graph with vertices as keys and outgoing - * edges as values. - */ -export function topologicalSort(graph: Map) { - const sorted = new Set(); - - // if (graph.size === 0) { - // return sorted; - // } - - // We clone the graph so we can remove handled nodes while we perform the - // topological ordering. If the cloned graph is _not_ empty at the end, we - // know we were not able to topologically order the graph. - const clonedGraph = new Map(graph.entries()); - - // First, find a list of "start nodes" which have no outgoing edges. At least - // one such node must exist in a non-empty acyclic graph. - const nodesWithNoEdges = [...clonedGraph.keys()].filter(name => { - const edges = clonedGraph.get(name) as T[]; - return edges.length === 0; - }); - - while (nodesWithNoEdges.length > 0) { - const processingNode = nodesWithNoEdges.pop() as T; - - // We know this node has no edges, so we can remove it - clonedGraph.delete(processingNode); - - sorted.add(processingNode); - - // Go through all nodes and remove all edges into `node` - [...clonedGraph.keys()].forEach(node => { - const edges = clonedGraph.get(node) as T[]; - const newEdges = edges.filter(edge => edge !== processingNode); - - clonedGraph.set(node, newEdges); - - if (newEdges.length === 0) { - nodesWithNoEdges.push(node); - } - }); - } - - if (clonedGraph.size > 0) { - const edgesLeft = JSON.stringify([...clonedGraph.entries()]); - throw new Error( - `Topological ordering did not complete, these edges could not be ordered: ${edgesLeft}` - ); - } - - return sorted; -} diff --git a/packages/kbn-system-loader/tsconfig.json b/packages/kbn-system-loader/tsconfig.json deleted file mode 100644 index c23b6635a5c19..0000000000000 --- a/packages/kbn-system-loader/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "declaration": true, - "outDir": "./target" - }, - "include": [ - "./src/**/*.ts" - ] -} From 96206bd092a5df46abe181c9a5940e665b899baf Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 22 Mar 2019 17:12:14 -0700 Subject: [PATCH 16/96] [eslint] merge custom rules into a single plugin (#33733) I'd like to add another custom eslint rule, but there isn't a very good place to do that right now. We have the `eslint-plugin-kibana-custom` package, which is super simple but isn't in the `@kbn` namespace and isn't included in the root eslint config, and `@kbn/eslint-plugin-license-header` is too specific, so I've merged those two packages into `@kbn/eslint-plugin-eslint`, which is a little redundant but allows is to refer to the rules within it as `@kbn/eslint/{rule}`, which feels nice. Thoughts? _**NOTE:**_ merging the eslint rules from the two packages means enabling prettier for the code from `@kbn/eslint-plugin-license-header`, all those changes are made in https://github.com/elastic/kibana/pull/33733/commits/42c7da6fe2631f513637ab07058be3f833ee7adb. [View the changes without the prettier updates](https://github.com/elastic/kibana/compare/b647f2b...74e07a0) --- .eslintignore | 1 - .eslintrc.js | 17 ++- package.json | 3 +- packages/eslint-plugin-kibana-custom/index.js | 14 --- .../eslint-plugin-kibana-custom/package.json | 10 -- .../README.md | 0 .../index.js | 1 + .../lib.js | 4 +- .../package.json | 2 +- .../__tests__/disallow_license_headers.js | 101 +++++++++--------- .../rules/__tests__/require_license_header.js | 65 ++++++----- .../rules/disallow_license_headers.js | 36 ++++--- .../rules/no_default_export.js | 29 +++++ .../rules/require_license_header.js | 43 ++++---- .../core_plugins/kibana/public/.eslintrc | 6 +- .../kibana/public/discover/_hit_sort_fn.js | 2 +- .../field_formats/__tests__/_conformance.js | 2 +- src/legacy/ui/public/.eslintrc | 5 +- .../hierarchical/_collect_branch.js | 2 +- .../agg_types/__tests__/agg_param_writer.js | 2 +- .../agg_types/__tests__/param_types/_json.js | 2 +- .../__tests__/param_types/_string.js | 2 +- .../__tests__/utils/_stub_agg_params.js | 2 +- src/legacy/ui/public/chrome/api/apps.js | 2 +- src/legacy/ui/public/chrome/api/template.js | 2 +- src/legacy/ui/public/chrome/index.js | 2 +- .../route_setup/load_default.js | 2 +- .../ui/public/jquery/find_test_subject.js | 2 +- src/legacy/ui/public/routes/index.js | 2 +- src/legacy/ui/public/routes/route_manager.js | 2 +- src/legacy/ui/public/utils/ipv4_address.ts | 2 +- src/legacy/ui/public/utils/mapping_setup.js | 2 +- src/legacy/ui/public/vis/agg_config_result.js | 2 +- src/legacy/ui/public/vislib/index.js | 2 +- .../layout/splits/gauge_chart/chart_split.js | 2 +- .../splits/gauge_chart/chart_title_split.js | 2 +- .../scroll_into_view_if_necessary.js | 2 +- .../ml/public/lib/angular_bootstrap_patch.js | 2 +- .../server/lib/encode_uri_query.js | 2 +- .../server/lib/pdf/assets/fonts/noto/index.js | 2 +- x-pack/test/functional/config.js | 2 +- 41 files changed, 196 insertions(+), 191 deletions(-) delete mode 100644 packages/eslint-plugin-kibana-custom/index.js delete mode 100644 packages/eslint-plugin-kibana-custom/package.json rename packages/{eslint-plugin-kibana-custom => kbn-eslint-plugin-eslint}/README.md (100%) rename packages/{kbn-eslint-plugin-license-header => kbn-eslint-plugin-eslint}/index.js (94%) rename packages/{kbn-eslint-plugin-license-header => kbn-eslint-plugin-eslint}/lib.js (93%) rename packages/{kbn-eslint-plugin-license-header => kbn-eslint-plugin-eslint}/package.json (81%) rename packages/{kbn-eslint-plugin-license-header => kbn-eslint-plugin-eslint}/rules/__tests__/disallow_license_headers.js (73%) rename packages/{kbn-eslint-plugin-license-header => kbn-eslint-plugin-eslint}/rules/__tests__/require_license_header.js (87%) rename packages/{kbn-eslint-plugin-license-header => kbn-eslint-plugin-eslint}/rules/disallow_license_headers.js (77%) create mode 100644 packages/kbn-eslint-plugin-eslint/rules/no_default_export.js rename packages/{kbn-eslint-plugin-license-header => kbn-eslint-plugin-eslint}/rules/require_license_header.js (81%) diff --git a/.eslintignore b/.eslintignore index f1448bf91ba03..8d43ffd8191c3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -18,7 +18,6 @@ bower_components /src/core/lib/kbn_internal_native_observable /packages/*/target /packages/eslint-config-kibana -/packages/eslint-plugin-kibana-custom /packages/kbn-es-query/src/kuery/ast/kuery.js /packages/kbn-es-query/src/kuery/ast/legacy_kuery.js /packages/kbn-pm/dist diff --git a/.eslintrc.js b/.eslintrc.js index 8e1e1e0f7c81a..8bfa6c5959668 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -34,6 +34,7 @@ const ELASTIC_LICENSE_HEADER = ` module.exports = { extends: ['@elastic/eslint-config-kibana', '@elastic/eslint-config-kibana/jest'], + plugins: ['@kbn/eslint-plugin-eslint'], settings: { 'import/resolver': { @@ -55,7 +56,7 @@ module.exports = { { files: [ '.eslintrc.js', - 'packages/eslint-plugin-kibana-custom/**/*', + 'packages/kbn-eslint-plugin-eslint/**/*', 'packages/kbn-config-schema/**/*', 'packages/kbn-pm/**/*', 'packages/kbn-es/**/*', @@ -87,7 +88,7 @@ module.exports = { { files: ['x-pack/test/functional/apps/**/*', 'x-pack/plugins/apm/**/*'], rules: { - 'kibana-custom/no-default-export': 'off', + '@kbn/eslint/no-default-export': 'off', 'import/no-named-as-default': 'off', }, }, @@ -242,7 +243,7 @@ module.exports = { 'packages/kbn-plugin-generator/**/*', 'packages/kbn-plugin-helpers/**/*', 'packages/kbn-eslint-import-resolver-kibana/**/*', - 'packages/kbn-eslint-plugin-license-header/**/*', + 'packages/kbn-eslint-plugin-eslint/**/*', 'x-pack/gulpfile.js', 'x-pack/dev-tools/mocha/setup_mocha.js', 'x-pack/scripts/*', @@ -267,15 +268,14 @@ module.exports = { */ { files: ['**/*.js'], - plugins: ['@kbn/eslint-plugin-license-header'], rules: { - '@kbn/license-header/require-license-header': [ + '@kbn/eslint/require-license-header': [ 'error', { license: APACHE_2_0_LICENSE_HEADER, }, ], - '@kbn/license-header/disallow-license-headers': [ + '@kbn/eslint/disallow-license-headers': [ 'error', { licenses: [ELASTIC_LICENSE_HEADER], @@ -289,15 +289,14 @@ module.exports = { */ { files: ['x-pack/**/*.js'], - plugins: ['@kbn/eslint-plugin-license-header'], rules: { - '@kbn/license-header/require-license-header': [ + '@kbn/eslint/require-license-header': [ 'error', { license: ELASTIC_LICENSE_HEADER, }, ], - '@kbn/license-header/disallow-license-headers': [ + '@kbn/eslint/disallow-license-headers': [ 'error', { licenses: [APACHE_2_0_LICENSE_HEADER], diff --git a/package.json b/package.json index 30b46e33b9ea5..fee468ac45ac8 100644 --- a/package.json +++ b/package.json @@ -254,11 +254,10 @@ "@babel/parser": "^7.3.4", "@babel/types": "^7.3.4", "@elastic/eslint-config-kibana": "0.15.0", - "@elastic/eslint-plugin-kibana-custom": "1.1.0", "@elastic/makelogs": "^4.4.0", "@kbn/es": "1.0.0", "@kbn/eslint-import-resolver-kibana": "2.0.0", - "@kbn/eslint-plugin-license-header": "1.0.0", + "@kbn/eslint-plugin-eslint": "1.0.0", "@kbn/plugin-generator": "1.0.0", "@kbn/test": "1.0.0", "@octokit/rest": "^15.10.0", diff --git a/packages/eslint-plugin-kibana-custom/index.js b/packages/eslint-plugin-kibana-custom/index.js deleted file mode 100644 index 3dada3ef3a610..0000000000000 --- a/packages/eslint-plugin-kibana-custom/index.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - rules: { - 'no-default-export': { - meta: { - schema: [] - }, - create: context => ({ - ExportDefaultDeclaration: (node) => { - context.report(node, 'Default exports not allowed.'); - } - }) - } - } -}; diff --git a/packages/eslint-plugin-kibana-custom/package.json b/packages/eslint-plugin-kibana-custom/package.json deleted file mode 100644 index 51a36e86dce52..0000000000000 --- a/packages/eslint-plugin-kibana-custom/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "@elastic/eslint-plugin-kibana-custom", - "version": "1.1.0", - "license": "Apache-2.0", - "description": "Custom ESLint rules for Kibana", - "repository": { - "type": "git", - "url": "https://github.com/elastic/kibana/tree/master/packages/%40elastic/eslint-plugin-kibana-custom" - } -} diff --git a/packages/eslint-plugin-kibana-custom/README.md b/packages/kbn-eslint-plugin-eslint/README.md similarity index 100% rename from packages/eslint-plugin-kibana-custom/README.md rename to packages/kbn-eslint-plugin-eslint/README.md diff --git a/packages/kbn-eslint-plugin-license-header/index.js b/packages/kbn-eslint-plugin-eslint/index.js similarity index 94% rename from packages/kbn-eslint-plugin-license-header/index.js rename to packages/kbn-eslint-plugin-eslint/index.js index 003c89b0c5f3b..70b42d92d4b74 100644 --- a/packages/kbn-eslint-plugin-license-header/index.js +++ b/packages/kbn-eslint-plugin-eslint/index.js @@ -21,5 +21,6 @@ module.exports = { rules: { 'require-license-header': require('./rules/require_license_header'), 'disallow-license-headers': require('./rules/disallow_license_headers'), + 'no-default-export': require('./rules/no_default_export'), }, }; diff --git a/packages/kbn-eslint-plugin-license-header/lib.js b/packages/kbn-eslint-plugin-eslint/lib.js similarity index 93% rename from packages/kbn-eslint-plugin-license-header/lib.js rename to packages/kbn-eslint-plugin-eslint/lib.js index 5d632b7c328c3..56684746c479f 100644 --- a/packages/kbn-eslint-plugin-license-header/lib.js +++ b/packages/kbn-eslint-plugin-eslint/lib.js @@ -31,14 +31,14 @@ exports.normalizeWhitespace = function normalizeWhitespace(string) { return string.replace(/\s+/g, ' '); }; -exports.init = function (context, program, initStep) { +exports.init = function(context, program, initStep) { try { return initStep(); } catch (error) { if (error.failedAssertion) { context.report({ node: program, - message: error.message + message: error.message, }); } else { throw error; diff --git a/packages/kbn-eslint-plugin-license-header/package.json b/packages/kbn-eslint-plugin-eslint/package.json similarity index 81% rename from packages/kbn-eslint-plugin-license-header/package.json rename to packages/kbn-eslint-plugin-eslint/package.json index 2c62a4232cf18..b35387384071e 100644 --- a/packages/kbn-eslint-plugin-license-header/package.json +++ b/packages/kbn-eslint-plugin-eslint/package.json @@ -1,5 +1,5 @@ { - "name": "@kbn/eslint-plugin-license-header", + "name": "@kbn/eslint-plugin-eslint", "version": "1.0.0", "private": true, "license": "Apache-2.0", diff --git a/packages/kbn-eslint-plugin-license-header/rules/__tests__/disallow_license_headers.js b/packages/kbn-eslint-plugin-eslint/rules/__tests__/disallow_license_headers.js similarity index 73% rename from packages/kbn-eslint-plugin-license-header/rules/__tests__/disallow_license_headers.js rename to packages/kbn-eslint-plugin-eslint/rules/__tests__/disallow_license_headers.js index 2ae6111166089..61fc1c112b8b2 100644 --- a/packages/kbn-eslint-plugin-license-header/rules/__tests__/disallow_license_headers.js +++ b/packages/kbn-eslint-plugin-eslint/rules/__tests__/disallow_license_headers.js @@ -21,15 +21,14 @@ const { RuleTester } = require('eslint'); const rule = require('../disallow_license_headers'); const dedent = require('dedent'); -const RULE_NAME = '@kbn/license-header/disallow-license-headers'; - const ruleTester = new RuleTester({ parser: 'babel-eslint', parserOptions: { - ecmaVersion: 2015 - } + ecmaVersion: 2015, + }, }); -ruleTester.run(RULE_NAME, rule, { + +ruleTester.run('@kbn/eslint/disallow-license-headers', rule, { valid: [ { code: dedent` @@ -38,11 +37,11 @@ ruleTester.run(RULE_NAME, rule, { console.log('foo') `, - options: [{ - licenses: [ - '// license' - ] - }], + options: [ + { + licenses: ['// license'], + }, + ], }, { code: dedent` @@ -51,12 +50,12 @@ ruleTester.run(RULE_NAME, rule, { console.log('foo') `, - options: [{ - licenses: [ - '/* license */', - ] - }], - } + options: [ + { + licenses: ['/* license */'], + }, + ], + }, ], invalid: [ @@ -70,8 +69,8 @@ ruleTester.run(RULE_NAME, rule, { errors: [ { message: '"licenses" option is required', - } - ] + }, + ], }, // license cannot contain multiple block comments @@ -80,16 +79,16 @@ ruleTester.run(RULE_NAME, rule, { console.log('foo') `, - options: [{ - licenses: [ - '/* one *//* two */' - ] - }], + options: [ + { + licenses: ['/* one *//* two */'], + }, + ], errors: [ { message: '"licenses[0]" option must only include a single comment', - } - ] + }, + ], }, // license cannot contain multiple line comments @@ -98,16 +97,16 @@ ruleTester.run(RULE_NAME, rule, { console.log('foo') `, - options: [{ - licenses: [ - `// one\n// two` - ] - }], + options: [ + { + licenses: [`// one\n// two`], + }, + ], errors: [ { message: '"licenses[0]" option must only include a single comment', - } - ] + }, + ], }, // license cannot contain expressions @@ -116,20 +115,22 @@ ruleTester.run(RULE_NAME, rule, { console.log('foo') `, - options: [{ - licenses: [ - '// old license', - dedent` + options: [ + { + licenses: [ + '// old license', + dedent` /* license */ console.log('hello world'); - ` - ] - }], + `, + ], + }, + ], errors: [ { message: '"licenses[1]" option must only include a single comment', - } - ] + }, + ], }, // license is not a single comment @@ -138,18 +139,16 @@ ruleTester.run(RULE_NAME, rule, { console.log('foo') `, - options: [{ - licenses: [ - '// old license', - '// older license', - `console.log('hello world');` - ] - }], + options: [ + { + licenses: ['// old license', '// older license', `console.log('hello world');`], + }, + ], errors: [ { message: '"licenses[2]" option must only include a single comment', - } - ] + }, + ], }, - ] + ], }); diff --git a/packages/kbn-eslint-plugin-license-header/rules/__tests__/require_license_header.js b/packages/kbn-eslint-plugin-eslint/rules/__tests__/require_license_header.js similarity index 87% rename from packages/kbn-eslint-plugin-license-header/rules/__tests__/require_license_header.js rename to packages/kbn-eslint-plugin-eslint/rules/__tests__/require_license_header.js index 86c7ea3244541..491ceb2290be1 100644 --- a/packages/kbn-eslint-plugin-license-header/rules/__tests__/require_license_header.js +++ b/packages/kbn-eslint-plugin-eslint/rules/__tests__/require_license_header.js @@ -21,15 +21,14 @@ const { RuleTester } = require('eslint'); const rule = require('../require_license_header'); const dedent = require('dedent'); -const RULE_NAME = '@kbn/license-header/require-license-header'; - const ruleTester = new RuleTester({ parser: 'babel-eslint', parserOptions: { - ecmaVersion: 2015 - } + ecmaVersion: 2015, + }, }); -ruleTester.run(RULE_NAME, rule, { + +ruleTester.run('@kbn/eslint/require-license-header', rule, { valid: [ { code: dedent` @@ -48,7 +47,7 @@ ruleTester.run(RULE_NAME, rule, { `, options: [{ license: '// license' }], - } + }, ], invalid: [ @@ -62,8 +61,8 @@ ruleTester.run(RULE_NAME, rule, { errors: [ { message: '"license" option is required', - } - ] + }, + ], }, // content cannot contain multiple block comments @@ -72,14 +71,12 @@ ruleTester.run(RULE_NAME, rule, { console.log('foo') `, - options: [ - { license: '/* one *//* two */' } - ], + options: [{ license: '/* one *//* two */' }], errors: [ { message: '"license" option must only include a single comment', - } - ] + }, + ], }, // content cannot contain multiple line comments @@ -88,14 +85,12 @@ ruleTester.run(RULE_NAME, rule, { console.log('foo') `, - options: [ - { license: `// one\n// two` } - ], + options: [{ license: `// one\n// two` }], errors: [ { message: '"license" option must only include a single comment', - } - ] + }, + ], }, // content cannot contain expressions @@ -109,14 +104,14 @@ ruleTester.run(RULE_NAME, rule, { license: dedent` /* license */ console.log('hello world'); - ` - } + `, + }, ], errors: [ { message: '"license" option must only include a single comment', - } - ] + }, + ], }, // content is not a single comment @@ -125,14 +120,12 @@ ruleTester.run(RULE_NAME, rule, { console.log('foo') `, - options: [ - { license: `console.log('hello world');` } - ], + options: [{ license: `console.log('hello world');` }], errors: [ { message: '"license" option must only include a single comment', - } - ] + }, + ], }, // missing license header @@ -145,19 +138,21 @@ ruleTester.run(RULE_NAME, rule, { errors: [ { message: 'File must start with a license header', - } + }, ], output: dedent` /* license */ console.log('foo') - ` + `, }, // strips newlines before the license comment { - code: '\n\n' + dedent` + code: + '\n\n' + + dedent` /* license */ console.log('foo') @@ -167,14 +162,14 @@ ruleTester.run(RULE_NAME, rule, { errors: [ { message: 'License header must be at the very beginning of the file', - } + }, ], output: dedent` /* license */ console.log('foo') - ` + `, }, // moves license header before other nodes if necessary @@ -189,7 +184,7 @@ ruleTester.run(RULE_NAME, rule, { errors: [ { message: 'License header must be at the very beginning of the file', - } + }, ], output: dedent` @@ -198,7 +193,7 @@ ruleTester.run(RULE_NAME, rule, { /* not license */ console.log('foo') - ` + `, }, - ] + ], }); diff --git a/packages/kbn-eslint-plugin-license-header/rules/disallow_license_headers.js b/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js similarity index 77% rename from packages/kbn-eslint-plugin-license-header/rules/disallow_license_headers.js rename to packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js index f7bd6fb68a785..0567307d18968 100644 --- a/packages/kbn-eslint-plugin-license-header/rules/disallow_license_headers.js +++ b/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js @@ -24,18 +24,20 @@ const { assert, normalizeWhitespace, init } = require('../lib'); module.exports = { meta: { fixable: 'code', - schema: [{ - type: 'object', - properties: { - licenses: { - type: 'array', - items: { - type: 'string' - } + schema: [ + { + type: 'object', + properties: { + licenses: { + type: 'array', + items: { + type: 'string', + }, + }, }, + additionalProperties: false, }, - additionalProperties: false, - }] + ], }, create: context => { return { @@ -49,8 +51,14 @@ module.exports = { return licenses.map((license, i) => { const parsed = babelEslint.parse(license); - assert(!parsed.body.length, `"licenses[${i}]" option must only include a single comment`); - assert(parsed.comments.length === 1, `"licenses[${i}]" option must only include a single comment`); + assert( + !parsed.body.length, + `"licenses[${i}]" option must only include a single comment` + ); + assert( + parsed.comments.length === 1, + `"licenses[${i}]" option must only include a single comment` + ); return normalizeWhitespace(parsed.comments[0].value); }); @@ -69,10 +77,10 @@ module.exports = { message: 'This license header is not allowed in this file.', fix(fixer) { return fixer.remove(node); - } + }, }); }); }, }; - } + }, }; diff --git a/packages/kbn-eslint-plugin-eslint/rules/no_default_export.js b/packages/kbn-eslint-plugin-eslint/rules/no_default_export.js new file mode 100644 index 0000000000000..660b9f8bb8b3c --- /dev/null +++ b/packages/kbn-eslint-plugin-eslint/rules/no_default_export.js @@ -0,0 +1,29 @@ +/* + * 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. + */ + +module.exports = { + meta: { + schema: [], + }, + create: context => ({ + ExportDefaultDeclaration: node => { + context.report(node, 'Default exports not allowed.'); + }, + }), +}; diff --git a/packages/kbn-eslint-plugin-license-header/rules/require_license_header.js b/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js similarity index 81% rename from packages/kbn-eslint-plugin-license-header/rules/require_license_header.js rename to packages/kbn-eslint-plugin-eslint/rules/require_license_header.js index 6aa1a6223b628..f3c9fcef1985e 100644 --- a/packages/kbn-eslint-plugin-license-header/rules/require_license_header.js +++ b/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js @@ -28,20 +28,22 @@ function isHashbang(text) { module.exports = { meta: { fixable: 'code', - schema: [{ - type: 'object', - properties: { - license: { - type: 'string', + schema: [ + { + type: 'object', + properties: { + license: { + type: 'string', + }, }, + additionalProperties: false, }, - additionalProperties: false, - }] + ], }, create: context => { return { Program(program) { - const license = init(context, program, function () { + const license = init(context, program, function() { const options = context.options[0] || {}; const license = options.license; @@ -49,11 +51,14 @@ module.exports = { const parsed = babelEslint.parse(license); assert(!parsed.body.length, '"license" option must only include a single comment'); - assert(parsed.comments.length === 1, '"license" option must only include a single comment'); + assert( + parsed.comments.length === 1, + '"license" option must only include a single comment' + ); return { source: license, - nodeValue: normalizeWhitespace(parsed.comments[0].value) + nodeValue: normalizeWhitespace(parsed.comments[0].value), }; }); @@ -62,9 +67,9 @@ module.exports = { } const sourceCode = context.getSourceCode(); - const comment = sourceCode.getAllComments().find(node => ( - normalizeWhitespace(node.value) === license.nodeValue - )); + const comment = sourceCode + .getAllComments() + .find(node => normalizeWhitespace(node.value) === license.nodeValue); // no licence comment if (!comment) { @@ -72,7 +77,7 @@ module.exports = { message: 'File must start with a license header', loc: { start: { line: 1, column: 0 }, - end: { line: 1, column: sourceCode.lines[0].length - 1 } + end: { line: 1, column: sourceCode.lines[0].length - 1 }, }, fix(fixer) { if (isHashbang(sourceCode.lines[0])) { @@ -80,13 +85,15 @@ module.exports = { } return fixer.replaceTextRange([0, 0], license.source + '\n\n'); - } + }, }); return; } // ensure there is nothing before the comment - const sourceBeforeNode = sourceCode.getText().slice(0, sourceCode.getIndexFromLoc(comment.loc.start)); + const sourceBeforeNode = sourceCode + .getText() + .slice(0, sourceCode.getIndexFromLoc(comment.loc.start)); if (sourceBeforeNode.length && !isHashbang(sourceBeforeNode)) { context.report({ node: comment, @@ -103,10 +110,10 @@ module.exports = { fixer.remove(comment), fixer.replaceTextRange([0, 0], license.source + '\n\n'), ]; - } + }, }); } }, }; - } + }, }; diff --git a/src/legacy/core_plugins/kibana/public/.eslintrc b/src/legacy/core_plugins/kibana/public/.eslintrc index bc1b9bbdf4949..95e3757201989 100644 --- a/src/legacy/core_plugins/kibana/public/.eslintrc +++ b/src/legacy/core_plugins/kibana/public/.eslintrc @@ -1,7 +1,3 @@ - -plugins: [ - '@elastic/eslint-plugin-kibana-custom' -] rules: no-console: 2 - '@elastic/kibana-custom/no-default-export': error + '@kbn/eslint/no-default-export': error diff --git a/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js b/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js index ce5311e46d655..c60f13bb76d4f 100644 --- a/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js +++ b/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js @@ -17,7 +17,7 @@ * under the License. */ -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function HitSortFnFactory() { /** * Creates a sort function that will resort hits based on the value diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js index 9e1f6015bd35f..d23b60cad87c8 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js @@ -43,7 +43,7 @@ const formatIds = [ 'static_lookup' ]; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default describe('conformance', function () { const getConfig = (...args) => config.get(...args); diff --git a/src/legacy/ui/public/.eslintrc b/src/legacy/ui/public/.eslintrc index 4285d367bdb5b..95e3757201989 100644 --- a/src/legacy/ui/public/.eslintrc +++ b/src/legacy/ui/public/.eslintrc @@ -1,6 +1,3 @@ -plugins: [ - '@elastic/eslint-plugin-kibana-custom' -] rules: no-console: 2 - '@elastic/kibana-custom/no-default-export': error + '@kbn/eslint/no-default-export': error diff --git a/src/legacy/ui/public/agg_response/hierarchical/_collect_branch.js b/src/legacy/ui/public/agg_response/hierarchical/_collect_branch.js index 1dc0b442d08d9..5339d453a7770 100644 --- a/src/legacy/ui/public/agg_response/hierarchical/_collect_branch.js +++ b/src/legacy/ui/public/agg_response/hierarchical/_collect_branch.js @@ -17,7 +17,7 @@ * under the License. */ -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function (leaf) { // walk up the branch for each parent function walk(item, memo) { diff --git a/src/legacy/ui/public/agg_types/__tests__/agg_param_writer.js b/src/legacy/ui/public/agg_types/__tests__/agg_param_writer.js index c4c619730092c..e162f59881376 100644 --- a/src/legacy/ui/public/agg_types/__tests__/agg_param_writer.js +++ b/src/legacy/ui/public/agg_types/__tests__/agg_param_writer.js @@ -22,7 +22,7 @@ import { VisProvider } from '../../vis'; import { aggTypes } from '..'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function AggParamWriterHelper(Private) { const Vis = Private(VisProvider); const stubbedLogstashIndexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); diff --git a/src/legacy/ui/public/agg_types/__tests__/param_types/_json.js b/src/legacy/ui/public/agg_types/__tests__/param_types/_json.js index 8c2a3f96073e8..516f1c95d71ff 100644 --- a/src/legacy/ui/public/agg_types/__tests__/param_types/_json.js +++ b/src/legacy/ui/public/agg_types/__tests__/param_types/_json.js @@ -22,7 +22,7 @@ import expect from 'expect.js'; import { BaseParamType } from '../../param_types/base'; import { JsonParamType } from '../../param_types/json'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default describe('JSON', function () { const paramName = 'json_test'; let aggParam; diff --git a/src/legacy/ui/public/agg_types/__tests__/param_types/_string.js b/src/legacy/ui/public/agg_types/__tests__/param_types/_string.js index 88d10c683f7c9..e11c50077a9c8 100644 --- a/src/legacy/ui/public/agg_types/__tests__/param_types/_string.js +++ b/src/legacy/ui/public/agg_types/__tests__/param_types/_string.js @@ -22,7 +22,7 @@ import expect from 'expect.js'; import { BaseParamType } from '../../param_types/base'; import { StringParamType } from '../../param_types/string'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default describe('String', function () { const paramName = 'json_test'; let aggParam; diff --git a/src/legacy/ui/public/agg_types/__tests__/utils/_stub_agg_params.js b/src/legacy/ui/public/agg_types/__tests__/utils/_stub_agg_params.js index 5f3eb734aaf7d..a9c46b09b5370 100644 --- a/src/legacy/ui/public/agg_types/__tests__/utils/_stub_agg_params.js +++ b/src/legacy/ui/public/agg_types/__tests__/utils/_stub_agg_params.js @@ -46,7 +46,7 @@ function ParamClassStub(parent, body) { * @param {PrivateLoader} Private - The private module loader, inject by passing this function to ngMock.inject() * @return {undefined} */ -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function stubParamClasses(Private) { const BaseAggParam = Private.stub( BaseParamType, diff --git a/src/legacy/ui/public/chrome/api/apps.js b/src/legacy/ui/public/chrome/api/apps.js index feb339e163a64..7779b9612b63e 100644 --- a/src/legacy/ui/public/chrome/api/apps.js +++ b/src/legacy/ui/public/chrome/api/apps.js @@ -20,7 +20,7 @@ import { clone, get } from 'lodash'; import { resolve } from 'url'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function (chrome, internals) { if (get(internals, 'app.navLink.url')) { diff --git a/src/legacy/ui/public/chrome/api/template.js b/src/legacy/ui/public/chrome/api/template.js index d1295dc8dddaa..58281c1af6c9d 100644 --- a/src/legacy/ui/public/chrome/api/template.js +++ b/src/legacy/ui/public/chrome/api/template.js @@ -17,7 +17,7 @@ * under the License. */ -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function (chrome, internals) { /** diff --git a/src/legacy/ui/public/chrome/index.js b/src/legacy/ui/public/chrome/index.js index ad62192704a1e..a322485b25513 100644 --- a/src/legacy/ui/public/chrome/index.js +++ b/src/legacy/ui/public/chrome/index.js @@ -19,5 +19,5 @@ import { chrome } from './chrome'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default chrome; diff --git a/src/legacy/ui/public/index_patterns/route_setup/load_default.js b/src/legacy/ui/public/index_patterns/route_setup/load_default.js index 6de1eb2b812a8..669b33d731983 100644 --- a/src/legacy/ui/public/index_patterns/route_setup/load_default.js +++ b/src/legacy/ui/public/index_patterns/route_setup/load_default.js @@ -59,7 +59,7 @@ function displayBanner() { }, 15000); } -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function (opts) { opts = opts || {}; const whenMissingRedirectTo = opts.whenMissingRedirectTo || null; diff --git a/src/legacy/ui/public/jquery/find_test_subject.js b/src/legacy/ui/public/jquery/find_test_subject.js index 857909d554ee2..e30b78a121cdc 100644 --- a/src/legacy/ui/public/jquery/find_test_subject.js +++ b/src/legacy/ui/public/jquery/find_test_subject.js @@ -19,7 +19,7 @@ import testSubjSelector from '@kbn/test-subj-selector'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function bindToJquery($) { /** diff --git a/src/legacy/ui/public/routes/index.js b/src/legacy/ui/public/routes/index.js index cf92b7de94e05..74e2613c66449 100644 --- a/src/legacy/ui/public/routes/index.js +++ b/src/legacy/ui/public/routes/index.js @@ -19,5 +19,5 @@ import { uiRoutes } from './routes'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default uiRoutes; diff --git a/src/legacy/ui/public/routes/route_manager.js b/src/legacy/ui/public/routes/route_manager.js index 94c7182b369a4..6cedf775cf576 100644 --- a/src/legacy/ui/public/routes/route_manager.js +++ b/src/legacy/ui/public/routes/route_manager.js @@ -23,7 +23,7 @@ import { wrapRouteWithPrep } from './wrap_route_with_prep'; import { RouteSetupManager } from './route_setup_manager'; import { parsePathToBreadcrumbs } from './breadcrumbs'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function RouteManager() { const self = this; const setup = new RouteSetupManager(); diff --git a/src/legacy/ui/public/utils/ipv4_address.ts b/src/legacy/ui/public/utils/ipv4_address.ts index b8bf3917c471d..5268d1ad97d24 100644 --- a/src/legacy/ui/public/utils/ipv4_address.ts +++ b/src/legacy/ui/public/utils/ipv4_address.ts @@ -30,7 +30,7 @@ function isIntegerInRange(integer: number, min: number, max: number) { ); } -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export // tslint:disable:no-default-export export default class Ipv4Address { private value: number; diff --git a/src/legacy/ui/public/utils/mapping_setup.js b/src/legacy/ui/public/utils/mapping_setup.js index b2589ca6b16b2..d02c6ea686b03 100644 --- a/src/legacy/ui/public/utils/mapping_setup.js +++ b/src/legacy/ui/public/utils/mapping_setup.js @@ -20,7 +20,7 @@ import angular from 'angular'; import _ from 'lodash'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function MappingSetupService() { const mappingSetup = this; diff --git a/src/legacy/ui/public/vis/agg_config_result.js b/src/legacy/ui/public/vis/agg_config_result.js index 75da837e6ee1c..f82c12585753a 100644 --- a/src/legacy/ui/public/vis/agg_config_result.js +++ b/src/legacy/ui/public/vis/agg_config_result.js @@ -19,7 +19,7 @@ import chrome from '../chrome'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function AggConfigResult(aggConfig, parent, value, key, filters) { this.key = key; this.value = value; diff --git a/src/legacy/ui/public/vislib/index.js b/src/legacy/ui/public/vislib/index.js index 0d527d08a28a0..515e5fc9da7f1 100644 --- a/src/legacy/ui/public/vislib/index.js +++ b/src/legacy/ui/public/vislib/index.js @@ -19,5 +19,5 @@ import { VislibProvider } from './vislib'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default VislibProvider; diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js b/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js index 906483966dc22..8e87a8be0b52c 100644 --- a/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js +++ b/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js @@ -19,7 +19,7 @@ import d3 from 'd3'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function ChartSplitFactory() { /* diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js b/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js index ad30bf91e9f00..331a5a60ec4fd 100644 --- a/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js +++ b/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js @@ -19,7 +19,7 @@ import d3 from 'd3'; -// eslint-disable-next-line @elastic/kibana-custom/no-default-export +// eslint-disable-next-line @kbn/eslint/no-default-export export default function ChartTitleSplitFactory() { /* diff --git a/test/functional/services/lib/web_element_wrapper/scroll_into_view_if_necessary.js b/test/functional/services/lib/web_element_wrapper/scroll_into_view_if_necessary.js index e135294ab95f4..75a690871c534 100644 --- a/test/functional/services/lib/web_element_wrapper/scroll_into_view_if_necessary.js +++ b/test/functional/services/lib/web_element_wrapper/scroll_into_view_if_necessary.js @@ -1,4 +1,4 @@ -/* eslint-disable @kbn/license-header/require-license-header */ +/* eslint-disable @kbn/eslint/require-license-header */ /** * @notice diff --git a/x-pack/plugins/ml/public/lib/angular_bootstrap_patch.js b/x-pack/plugins/ml/public/lib/angular_bootstrap_patch.js index 57448ead2f679..a13b151c26557 100644 --- a/x-pack/plugins/ml/public/lib/angular_bootstrap_patch.js +++ b/x-pack/plugins/ml/public/lib/angular_bootstrap_patch.js @@ -1,4 +1,4 @@ -/* eslint-disable @kbn/license-header/require-license-header */ +/* eslint-disable @kbn/eslint/require-license-header */ /** * @notice diff --git a/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/encode_uri_query.js b/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/encode_uri_query.js index 999144a5ce1c5..a9329a7b42da8 100644 --- a/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/encode_uri_query.js +++ b/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/encode_uri_query.js @@ -1,4 +1,4 @@ -/* eslint-disable @kbn/license-header/require-license-header */ +/* eslint-disable @kbn/eslint/require-license-header */ // This function was extracted from angular v1.3 diff --git a/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/pdf/assets/fonts/noto/index.js b/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/pdf/assets/fonts/noto/index.js index 9b78d73b39449..ee0e7c81e4849 100644 --- a/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/pdf/assets/fonts/noto/index.js +++ b/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/pdf/assets/fonts/noto/index.js @@ -1,4 +1,4 @@ -/* eslint-disable @kbn/license-header/require-license-header */ +/* eslint-disable @kbn/eslint/require-license-header */ /** * @notice * diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index f1cfd20210000..82270b7ac00d5 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -/* eslint-disable kibana-custom/no-default-export */ +/* eslint-disable @kbn/eslint/no-default-export */ import { resolve } from 'path'; From 53323d3d8af7b548a55427262ea2d836b9e9c582 Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Sun, 24 Mar 2019 11:00:52 +0200 Subject: [PATCH 17/96] Deleted unused directives from angular-boostrap (#33564) * Deleted unused directives - alert - pagination - pager - bar - tooltipPopup - tooltipHtmlUnsafePopup --- NOTICE.txt | 26 - src/dev/precommit_hook/casing_check_config.js | 3 - .../core_plugins/console/public/console.js | 2 - .../console/public/webpackShims/.eslintrc | 2 - .../webpackShims/ui-bootstrap-custom.js | 729 ------------------ .../public/angular-bootstrap/alert/alert.html | 10 - .../public/angular-bootstrap/alert/alert.js | 20 - .../ui/public/angular-bootstrap/index.js | 82 +- .../angular-bootstrap/pagination/pager.html | 4 - .../pagination/pagination.html | 7 - .../pagination/pagination.js | 228 ------ .../angular-bootstrap/progressbar/bar.html | 2 +- .../progressbar/progressbar.js | 52 +- .../timepicker/timepicker.html | 26 - .../timepicker/timepicker.js | 254 ------ .../{position => tooltip}/position.js | 0 .../tooltip/tooltip-html-unsafe-popup.html | 8 +- .../tooltip/tooltip-popup.html | 8 +- .../angular-bootstrap/tooltip/tooltip.js | 38 +- .../typeahead/typeahead-match.html | 1 - .../typeahead/typeahead-popup.html | 5 - .../angular-bootstrap/typeahead/typeahead.js | 398 ---------- .../translations/translations/zh-CN.json | 7 - 23 files changed, 70 insertions(+), 1842 deletions(-) delete mode 100644 src/legacy/core_plugins/console/public/webpackShims/.eslintrc delete mode 100755 src/legacy/core_plugins/console/public/webpackShims/ui-bootstrap-custom.js delete mode 100755 src/legacy/ui/public/angular-bootstrap/alert/alert.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/alert/alert.js delete mode 100755 src/legacy/ui/public/angular-bootstrap/pagination/pager.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/pagination/pagination.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/pagination/pagination.js mode change 100755 => 100644 src/legacy/ui/public/angular-bootstrap/progressbar/bar.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/timepicker/timepicker.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/timepicker/timepicker.js rename src/legacy/ui/public/angular-bootstrap/{position => tooltip}/position.js (100%) mode change 100755 => 100644 src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-html-unsafe-popup.html mode change 100755 => 100644 src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-match.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-popup.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/typeahead/typeahead.js diff --git a/NOTICE.txt b/NOTICE.txt index cd6f783e530b4..216591e2b4150 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -80,32 +80,6 @@ used. Logarithmic ticks are places at powers of ten and at half those values if there are not to many ticks already (e.g. [1, 5, 10, 50, 100]). For details, see https://github.com/flot/flot/pull/1328 ---- -This product bundles angular-ui-bootstrap@0.12.1 which is available under a -"MIT" license. - -The MIT License - -Copyright (c) 2012-2014 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - --- This product bundles bootstrap@3.3.6 which is available under a "MIT" license. diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index 8eb404749219a..fefb205e0289c 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -107,7 +107,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/console/public/webpackShims/ui-bootstrap-custom.js', 'src/legacy/core_plugins/kibana/public/assets/play-circle.svg', 'src/legacy/core_plugins/tests_bundle/webpackShims/angular-mocks.js', 'src/legacy/core_plugins/tile_map/public/__tests__/scaledCircleMarkers.png', @@ -123,8 +122,6 @@ export const TEMPORARILY_IGNORED_PATHS = [ 'src/legacy/ui/public/angular-bootstrap/bindHtml/bindHtml.js', 'src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-html-unsafe-popup.html', 'src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html', - 'src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-match.html', - 'src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-popup.html', 'src/legacy/ui/public/assets/favicons/android-chrome-192x192.png', 'src/legacy/ui/public/assets/favicons/android-chrome-256x256.png', 'src/legacy/ui/public/assets/favicons/android-chrome-512x512.png', diff --git a/src/legacy/core_plugins/console/public/console.js b/src/legacy/core_plugins/console/public/console.js index 461423ce4ebbb..3976e38302879 100644 --- a/src/legacy/core_plugins/console/public/console.js +++ b/src/legacy/core_plugins/console/public/console.js @@ -21,9 +21,7 @@ import uiRoutes from 'ui/routes'; import template from './index.html'; require('brace'); -require('ui-bootstrap-custom'); -require('ui/modules').get('kibana', ['sense.ui.bootstrap']); require('ui/tooltip'); require('ui/autoload/styles'); diff --git a/src/legacy/core_plugins/console/public/webpackShims/.eslintrc b/src/legacy/core_plugins/console/public/webpackShims/.eslintrc deleted file mode 100644 index 761851c90eea5..0000000000000 --- a/src/legacy/core_plugins/console/public/webpackShims/.eslintrc +++ /dev/null @@ -1,2 +0,0 @@ ---- -root: true diff --git a/src/legacy/core_plugins/console/public/webpackShims/ui-bootstrap-custom.js b/src/legacy/core_plugins/console/public/webpackShims/ui-bootstrap-custom.js deleted file mode 100755 index 55ebc7aba8e47..0000000000000 --- a/src/legacy/core_plugins/console/public/webpackShims/ui-bootstrap-custom.js +++ /dev/null @@ -1,729 +0,0 @@ -/* - * angular-ui-bootstrap - * http://angular-ui.github.io/bootstrap/ - - * Version: 0.14.2 - 2015-10-17 - * License: MIT - */ - -/* @notice - * This product bundles angular-ui-bootstrap@0.12.1 which is available under a - * "MIT" license. - * - * The MIT License - * - * Copyright (c) 2012-2014 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112 - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -angular.module("sense.ui.bootstrap", ["sense.ui.bootstrap.tpls","sense.ui.bootstrap.typeahead","sense.ui.bootstrap.position"]); -angular.module("sense.ui.bootstrap.tpls", ["sense/template/typeahead/typeahead-match.html","sense/template/typeahead/typeahead-popup.html"]); -angular.module('sense.ui.bootstrap.typeahead', ['sense.ui.bootstrap.position']) - -/** - * A helper service that can parse typeahead's syntax (string provided by users) - * Extracted to a separate service for ease of unit testing - */ - .factory('senseUibTypeaheadParser', ['$parse', function($parse) { - // 00000111000000000000022200000000000000003333333333333330000000000044000 - var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; - return { - parse: function(input) { - var match = input.match(TYPEAHEAD_REGEXP); - if (!match) { - throw new Error( - 'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + - ' but got "' + input + '".'); - } - - return { - itemName: match[3], - source: $parse(match[4]), - viewMapper: $parse(match[2] || match[1]), - modelMapper: $parse(match[1]) - }; - } - }; - }]) - - .controller('SenseUibTypeaheadController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$senseUibPosition', 'senseUibTypeaheadParser', - function(originalScope, element, attrs, $compile, $parse, $q, $timeout, $document, $window, $rootScope, $position, typeaheadParser) { - var HOT_KEYS = [9, 13, 27, 38, 40]; - var eventDebounceTime = 200; - var modelCtrl, ngModelOptions; - //SUPPORTED ATTRIBUTES (OPTIONS) - - //minimal no of characters that needs to be entered before typeahead kicks-in - var minLength = originalScope.$eval(attrs.typeaheadMinLength); - if (!minLength && minLength !== 0) { - minLength = 1; - } - - //minimal wait time after last character typed before typeahead kicks-in - var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; - - //should it restrict model values to the ones selected from the popup only? - var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; - - //binding to a variable that indicates if matches are being retrieved asynchronously - var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; - - //a callback executed when a match is selected - var onSelectCallback = $parse(attrs.typeaheadOnSelect); - - //should it select highlighted popup value when losing focus? - var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false; - - //binding to a variable that indicates if there were no results after the query is completed - var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop; - - var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; - - var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; - - var appendToElementId = attrs.typeaheadAppendToElementId || false; - - var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; - - //If input matches an item of the list exactly, select it automatically - var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false; - - //INTERNAL VARIABLES - - //model setter executed upon match selection - var parsedModel = $parse(attrs.ngModel); - var invokeModelSetter = $parse(attrs.ngModel + '($$$p)'); - var $setModelValue = function(scope, newValue) { - if (angular.isFunction(parsedModel(originalScope)) && - ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) { - return invokeModelSetter(scope, {$$$p: newValue}); - } else { - return parsedModel.assign(scope, newValue); - } - }; - - //expressions used by typeahead - var parserResult = typeaheadParser.parse(attrs.senseUibTypeahead); - - var hasFocus; - - //Used to avoid bug in iOS webview where iOS keyboard does not fire - //mousedown & mouseup events - //Issue #3699 - var selected; - - //create a child scope for the typeahead directive so we are not polluting original scope - //with typeahead-specific data (matches, query etc.) - var scope = originalScope.$new(); - var offDestroy = originalScope.$on('$destroy', function() { - scope.$destroy(); - }); - scope.$on('$destroy', offDestroy); - - // WAI-ARIA - var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000); - element.attr({ - 'aria-autocomplete': 'list', - 'aria-expanded': false, - 'aria-owns': popupId - }); - - //pop-up element used to display matches - var popUpEl = angular.element('
'); - popUpEl.attr({ - id: popupId, - matches: 'matches', - active: 'activeIdx', - select: 'select(activeIdx)', - 'move-in-progress': 'moveInProgress', - query: 'query', - position: 'position' - }); - //custom item template - if (angular.isDefined(attrs.typeaheadTemplateUrl)) { - popUpEl.attr('template-url', attrs.typeaheadTemplateUrl); - } - - if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) { - popUpEl.attr('popup-template-url', attrs.typeaheadPopupTemplateUrl); - } - - var resetMatches = function() { - scope.matches = []; - scope.activeIdx = -1; - element.attr('aria-expanded', false); - }; - - var getMatchId = function(index) { - return popupId + '-option-' + index; - }; - - // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead. - // This attribute is added or removed automatically when the `activeIdx` changes. - scope.$watch('activeIdx', function(index) { - if (index < 0) { - element.removeAttr('aria-activedescendant'); - } else { - element.attr('aria-activedescendant', getMatchId(index)); - } - }); - - var inputIsExactMatch = function(inputValue, index) { - if (scope.matches.length > index && inputValue) { - return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase(); - } - - return false; - }; - - var getMatchesAsync = function(inputValue) { - var locals = {$viewValue: inputValue}; - isLoadingSetter(originalScope, true); - isNoResultsSetter(originalScope, false); - $q.when(parserResult.source(originalScope, locals)).then(function(matches) { - //it might happen that several async queries were in progress if a user were typing fast - //but we are interested only in responses that correspond to the current view value - var onCurrentRequest = (inputValue === modelCtrl.$viewValue); - if (onCurrentRequest && hasFocus) { - if (matches && matches.length > 0) { - scope.activeIdx = focusFirst ? 0 : -1; - isNoResultsSetter(originalScope, false); - scope.matches.length = 0; - - //transform labels - for (var i = 0; i < matches.length; i++) { - locals[parserResult.itemName] = matches[i]; - scope.matches.push({ - id: getMatchId(i), - label: parserResult.viewMapper(scope, locals), - model: matches[i] - }); - } - - scope.query = inputValue; - //position pop-up with matches - we need to re-calculate its position each time we are opening a window - //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page - //due to other elements being rendered - recalculatePosition(); - - element.attr('aria-expanded', true); - - //Select the single remaining option if user input matches - if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) { - scope.select(0); - } - } else { - resetMatches(); - isNoResultsSetter(originalScope, true); - } - } - if (onCurrentRequest) { - isLoadingSetter(originalScope, false); - } - }, function() { - resetMatches(); - isLoadingSetter(originalScope, false); - isNoResultsSetter(originalScope, true); - }); - }; - - // bind events only if appendToBody params exist - performance feature - if (appendToBody) { - angular.element($window).bind('resize', fireRecalculating); - $document.find('body').bind('scroll', fireRecalculating); - } - - // Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later - var timeoutEventPromise; - - // Default progress type - scope.moveInProgress = false; - - function fireRecalculating() { - if (!scope.moveInProgress) { - scope.moveInProgress = true; - scope.$digest(); - } - - // Cancel previous timeout - if (timeoutEventPromise) { - $timeout.cancel(timeoutEventPromise); - } - - // Debounced executing recalculate after events fired - timeoutEventPromise = $timeout(function() { - // if popup is visible - if (scope.matches.length) { - recalculatePosition(); - } - - scope.moveInProgress = false; - }, eventDebounceTime); - } - - // recalculate actual position and set new values to scope - // after digest loop is popup in right position - function recalculatePosition() { - scope.position = appendToBody ? $position.offset(element) : $position.position(element); - scope.position.top += element.prop('offsetHeight'); - } - - //we need to propagate user's query so we can highlight matches - scope.query = undefined; - - //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later - var timeoutPromise; - - var scheduleSearchWithTimeout = function(inputValue) { - timeoutPromise = $timeout(function() { - getMatchesAsync(inputValue); - }, waitTime); - }; - - var cancelPreviousTimeout = function() { - if (timeoutPromise) { - $timeout.cancel(timeoutPromise); - } - }; - - resetMatches(); - - scope.select = function(activeIdx) { - //called from within the $digest() cycle - var locals = {}; - var model, item; - - selected = true; - locals[parserResult.itemName] = item = scope.matches[activeIdx].model; - model = parserResult.modelMapper(originalScope, locals); - $setModelValue(originalScope, model); - modelCtrl.$setValidity('editable', true); - modelCtrl.$setValidity('parse', true); - - onSelectCallback(originalScope, { - $item: item, - $model: model, - $label: parserResult.viewMapper(originalScope, locals) - }); - - resetMatches(); - - //return focus to the input element if a match was selected via a mouse click event - // use timeout to avoid $rootScope:inprog error - if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) { - $timeout(function() { element[0].focus(); }, 0, false); - } - }; - - //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27) - element.bind('keydown', function(evt) { - //typeahead is open and an "interesting" key was pressed - if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { - return; - } - - // if there's nothing selected (i.e. focusFirst) and enter or tab is hit, clear the results - if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13)) { - resetMatches(); - scope.$digest(); - return; - } - - evt.preventDefault(); - - if (evt.which === 40) { - scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; - scope.$digest(); - } else if (evt.which === 38) { - scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; - scope.$digest(); - } else if (evt.which === 13 || evt.which === 9) { - scope.$apply(function () { - scope.select(scope.activeIdx); - }); - } else if (evt.which === 27) { - evt.stopPropagation(); - - resetMatches(); - scope.$digest(); - } - }); - - element.bind('blur', function() { - if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) { - selected = true; - scope.$apply(function() { - scope.select(scope.activeIdx); - }); - } - hasFocus = false; - selected = false; - }); - - // Keep reference to click handler to unbind it. - var dismissClickHandler = function(evt) { - // Issue #3973 - // Firefox treats right click as a click on document - if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) { - resetMatches(); - if (!$rootScope.$$phase) { - scope.$digest(); - } - } - }; - - $document.bind('click', dismissClickHandler); - - originalScope.$on('$destroy', function() { - $document.unbind('click', dismissClickHandler); - if (appendToBody || appendToElementId) { - $popup.remove(); - } - // Prevent jQuery cache memory leak - popUpEl.remove(); - }); - - var $popup = $compile(popUpEl)(scope); - - if (appendToBody) { - $document.find('body').append($popup); - } else if (appendToElementId !== false) { - angular.element($document[0].getElementById(appendToElementId)).append($popup); - } else { - element.after($popup); - } - - this.init = function(_modelCtrl, _ngModelOptions) { - modelCtrl = _modelCtrl; - ngModelOptions = _ngModelOptions; - - //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM - //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue - modelCtrl.$parsers.unshift(function(inputValue) { - hasFocus = true; - - if (minLength === 0 || inputValue && inputValue.length >= minLength) { - if (waitTime > 0) { - cancelPreviousTimeout(); - scheduleSearchWithTimeout(inputValue); - } else { - getMatchesAsync(inputValue); - } - } else { - isLoadingSetter(originalScope, false); - cancelPreviousTimeout(); - resetMatches(); - } - - if (isEditable) { - return inputValue; - } else { - if (!inputValue) { - // Reset in case user had typed something previously. - modelCtrl.$setValidity('editable', true); - return null; - } else { - modelCtrl.$setValidity('editable', false); - return undefined; - } - } - }); - - modelCtrl.$formatters.push(function(modelValue) { - var candidateViewValue, emptyViewValue; - var locals = {}; - - // The validity may be set to false via $parsers (see above) if - // the model is restricted to selected values. If the model - // is set manually it is considered to be valid. - if (!isEditable) { - modelCtrl.$setValidity('editable', true); - } - - if (inputFormatter) { - locals.$model = modelValue; - return inputFormatter(originalScope, locals); - } else { - //it might happen that we don't have enough info to properly render input value - //we need to check for this situation and simply return model value if we can't apply custom formatting - locals[parserResult.itemName] = modelValue; - candidateViewValue = parserResult.viewMapper(originalScope, locals); - locals[parserResult.itemName] = undefined; - emptyViewValue = parserResult.viewMapper(originalScope, locals); - - return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue; - } - }); - }; - }]) - - .directive('senseUibTypeahead', function() { - return { - controller: 'SenseUibTypeaheadController', - require: ['ngModel', '^?ngModelOptions', 'senseUibTypeahead'], - link: function(originalScope, element, attrs, ctrls) { - ctrls[2].init(ctrls[0], ctrls[1]); - } - }; - }) - - .directive('senseUibTypeaheadPopup', function() { - return { - scope: { - matches: '=', - query: '=', - active: '=', - position: '&', - moveInProgress: '=', - select: '&' - }, - replace: true, - templateUrl: function(element, attrs) { - return attrs.popupTemplateUrl || 'sense/template/typeahead/typeahead-popup.html'; - }, - link: function(scope, element, attrs) { - scope.templateUrl = attrs.templateUrl; - - scope.isOpen = function() { - return scope.matches.length > 0; - }; - - scope.isActive = function(matchIdx) { - return scope.active == matchIdx; - }; - - scope.selectActive = function(matchIdx) { - scope.active = matchIdx; - }; - - scope.selectMatch = function(activeIdx) { - scope.select({activeIdx:activeIdx}); - }; - } - }; - }) - - .directive('senseUibTypeaheadMatch', ['$templateCache', '$compile', '$parse', function($templateCache, $compile, $parse) { - return { - scope: { - index: '=', - match: '=', - query: '=' - }, - link:function(scope, element, attrs) { - var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'sense/template/typeahead/typeahead-match.html'; - $compile($templateCache.get(tplUrl).trim())(scope, function(clonedElement) { - element.replaceWith(clonedElement); - }); - } - }; - }]) - - .filter('senseUibTypeaheadHighlight', ['$sce', '$injector', '$log', function($sce, $injector, $log) { - var isSanitizePresent; - isSanitizePresent = $injector.has('$sanitize'); - - function escapeRegexp(queryToEscape) { - // Regex: capture the whole query string and replace it with the string that will be used to match - // the results, for example if the capture is "a" the result will be \a - return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); - } - - function containsHtml(matchItem) { - return /<.*>/g.test(matchItem); - } - - return function(matchItem, query) { - if (!isSanitizePresent && containsHtml(matchItem)) { - $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger - } - matchItem = query? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; // Replaces the capture string with a the same string inside of a "strong" tag - if (!isSanitizePresent) { - matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive - } - return matchItem; - }; - }]); - -angular.module('sense.ui.bootstrap.position', []) - -/** - * A set of utility methods that can be use to retrieve position of DOM elements. - * It is meant to be used where we need to absolute-position DOM elements in - * relation to other, existing elements (this is the case for tooltips, popovers, - * typeahead suggestions etc.). - */ - .factory('$senseUibPosition', ['$document', '$window', function($document, $window) { - function getStyle(el, cssprop) { - if (el.currentStyle) { //IE - return el.currentStyle[cssprop]; - } else if ($window.getComputedStyle) { - return $window.getComputedStyle(el)[cssprop]; - } - // finally try and get inline style - return el.style[cssprop]; - } - - /** - * Checks if a given element is statically positioned - * @param element - raw DOM element - */ - function isStaticPositioned(element) { - return (getStyle(element, 'position') || 'static' ) === 'static'; - } - - /** - * returns the closest, non-statically positioned parentOffset of a given element - * @param element - */ - var parentOffsetEl = function(element) { - var docDomEl = $document[0]; - var offsetParent = element.offsetParent || docDomEl; - while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) { - offsetParent = offsetParent.offsetParent; - } - return offsetParent || docDomEl; - }; - - return { - /** - * Provides read-only equivalent of jQuery's position function: - * http://api.jquery.com/position/ - */ - position: function(element) { - var elBCR = this.offset(element); - var offsetParentBCR = { top: 0, left: 0 }; - var offsetParentEl = parentOffsetEl(element[0]); - if (offsetParentEl != $document[0]) { - offsetParentBCR = this.offset(angular.element(offsetParentEl)); - offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; - offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; - } - - var boundingClientRect = element[0].getBoundingClientRect(); - return { - width: boundingClientRect.width || element.prop('offsetWidth'), - height: boundingClientRect.height || element.prop('offsetHeight'), - top: elBCR.top - offsetParentBCR.top, - left: elBCR.left - offsetParentBCR.left - }; - }, - - /** - * Provides read-only equivalent of jQuery's offset function: - * http://api.jquery.com/offset/ - */ - offset: function(element) { - var boundingClientRect = element[0].getBoundingClientRect(); - return { - width: boundingClientRect.width || element.prop('offsetWidth'), - height: boundingClientRect.height || element.prop('offsetHeight'), - top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), - left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) - }; - }, - - /** - * Provides coordinates for the targetEl in relation to hostEl - */ - positionElements: function(hostEl, targetEl, positionStr, appendToBody) { - var positionStrParts = positionStr.split('-'); - var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center'; - - var hostElPos, - targetElWidth, - targetElHeight, - targetElPos; - - hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); - - targetElWidth = targetEl.prop('offsetWidth'); - targetElHeight = targetEl.prop('offsetHeight'); - - var shiftWidth = { - center: function() { - return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; - }, - left: function() { - return hostElPos.left; - }, - right: function() { - return hostElPos.left + hostElPos.width; - } - }; - - var shiftHeight = { - center: function() { - return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; - }, - top: function() { - return hostElPos.top; - }, - bottom: function() { - return hostElPos.top + hostElPos.height; - } - }; - - switch (pos0) { - case 'right': - targetElPos = { - top: shiftHeight[pos1](), - left: shiftWidth[pos0]() - }; - break; - case 'left': - targetElPos = { - top: shiftHeight[pos1](), - left: hostElPos.left - targetElWidth - }; - break; - case 'bottom': - targetElPos = { - top: shiftHeight[pos0](), - left: shiftWidth[pos1]() - }; - break; - default: - targetElPos = { - top: hostElPos.top - targetElHeight, - left: shiftWidth[pos1]() - }; - break; - } - - return targetElPos; - } - }; - }]); - -angular.module("sense/template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("sense/template/typeahead/typeahead-match.html", - "
\n" + - ""); -}]); - -angular.module("sense/template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("sense/template/typeahead/typeahead-popup.html", - "
    \n" + - "
  • \n" + - "
    \n" + - "
  • \n" + - "
\n" + - ""); -}]); diff --git a/src/legacy/ui/public/angular-bootstrap/alert/alert.html b/src/legacy/ui/public/angular-bootstrap/alert/alert.html deleted file mode 100755 index 258164482cd18..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/alert/alert.html +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/src/legacy/ui/public/angular-bootstrap/alert/alert.js b/src/legacy/ui/public/angular-bootstrap/alert/alert.js deleted file mode 100755 index fd16aa49014c1..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/alert/alert.js +++ /dev/null @@ -1,20 +0,0 @@ -angular.module('ui.bootstrap.alert', []) - -.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) { - $scope.closeable = 'close' in $attrs; - this.close = $scope.close; -}]) - -.directive('alert', function () { - return { - restrict:'EA', - controller:'AlertController', - templateUrl:'template/alert/alert.html', - transclude:true, - replace:true, - scope: { - type: '@', - close: '&' - } - }; -}) diff --git a/src/legacy/ui/public/angular-bootstrap/index.js b/src/legacy/ui/public/angular-bootstrap/index.js index 6743511a55eb0..7378cf90e3708 100644 --- a/src/legacy/ui/public/angular-bootstrap/index.js +++ b/src/legacy/ui/public/angular-bootstrap/index.js @@ -23,49 +23,27 @@ uiModules.get('kibana', [ angular.module('ui.bootstrap', [ 'ui.bootstrap.tpls', 'ui.bootstrap.transition', - 'ui.bootstrap.alert', 'ui.bootstrap.bindHtml', - 'ui.bootstrap.position', 'ui.bootstrap.modal', - 'ui.bootstrap.pagination', 'ui.bootstrap.tooltip', 'ui.bootstrap.progressbar', - 'ui.bootstrap.timepicker', - 'ui.bootstrap.typeahead' ]); angular.module('ui.bootstrap.tpls', [ - 'template/alert/alert.html', 'template/modal/backdrop.html', - 'template/modal/window.html', - 'template/pagination/pager.html', - 'template/pagination/pagination.html', - 'template/tooltip/tooltip-html-unsafe-popup.html', - 'template/tooltip/tooltip-popup.html', - 'template/progressbar/bar.html', + 'template/modal/window.html', + 'template/tooltip/tooltip-html-unsafe-popup.html', + 'template/tooltip/tooltip-popup.html', + 'template/progressbar/bar.html', 'template/progressbar/progress.html', 'template/progressbar/progressbar.html', - 'template/timepicker/timepicker.html', - 'template/typeahead/typeahead-match.html', - 'template/typeahead/typeahead-popup.html' ]); -import './alert/alert'; import './bindHtml/bindHtml'; import './modal/modal'; -import './pagination/pagination'; -import './position/position'; import './progressbar/progressbar'; -import './timepicker/timepicker'; import './tooltip/tooltip'; import './transition/transition'; -import './typeahead/typeahead'; - -import alert from './alert/alert.html'; - -angular.module('template/alert/alert.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/alert/alert.html', alert); -}]); import backdrop from './modal/backdrop.html'; @@ -79,35 +57,23 @@ angular.module('template/modal/window.html', []).run(['$templateCache', function $templateCache.put('template/modal/window.html', modal); }]); -import pager from './pagination/pager.html'; - -angular.module('template/pagination/pager.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/pagination/pager.html', pager); -}]); - -import pagination from './pagination/pagination.html'; - -angular.module('template/pagination/pagination.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/pagination/pagination.html', pagination); -}]); +import tooltipUnsafePopup from './tooltip/tooltip-html-unsafe-popup.html'; -import tooltipUnsafePopup from './tooltip/tooltip-html-unsafe-popup.html'; - -angular.module('template/tooltip/tooltip-html-unsafe-popup.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/tooltip/tooltip-html-unsafe-popup.html', tooltipUnsafePopup); -}]); +angular.module('template/tooltip/tooltip-html-unsafe-popup.html', []).run(['$templateCache', function($templateCache) { + $templateCache.put('template/tooltip/tooltip-html-unsafe-popup.html', tooltipUnsafePopup); +}]); -import tooltipPopup from './tooltip/tooltip-popup.html'; +import tooltipPopup from './tooltip/tooltip-popup.html'; -angular.module('template/tooltip/tooltip-popup.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/tooltip/tooltip-popup.html', tooltipPopup); +angular.module('template/tooltip/tooltip-popup.html', []).run(['$templateCache', function($templateCache) { + $templateCache.put('template/tooltip/tooltip-popup.html', tooltipPopup); }]); -import bar from './progressbar/bar.html'; +import bar from './progressbar/bar.html'; -angular.module('template/progressbar/bar.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/progressbar/bar.html', bar); -}]); + angular.module('template/progressbar/bar.html', []).run(['$templateCache', function($templateCache) { + $templateCache.put('template/progressbar/bar.html', bar); +}]); import progress from './progressbar/progress.html'; @@ -120,21 +86,3 @@ import progressbar from './progressbar/progressbar.html'; angular.module('template/progressbar/progressbar.html', []).run(['$templateCache', function($templateCache) { $templateCache.put('template/progressbar/progressbar.html', progressbar); }]); - -import timepicker from './timepicker/timepicker.html'; - -angular.module('template/timepicker/timepicker.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/timepicker/timepicker.html', timepicker); -}]); - -import typeaheadMatch from './typeahead/typeahead-match.html'; - -angular.module('template/typeahead/typeahead-match.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/typeahead/typeahead-match.html', typeaheadMatch); -}]); - -import typeaheadPopup from './typeahead/typeahead-popup.html'; - -angular.module('template/typeahead/typeahead-popup.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/typeahead/typeahead-popup.html', typeaheadPopup); -}]); diff --git a/src/legacy/ui/public/angular-bootstrap/pagination/pager.html b/src/legacy/ui/public/angular-bootstrap/pagination/pager.html deleted file mode 100755 index ca150de164255..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/pagination/pager.html +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/pagination/pagination.html b/src/legacy/ui/public/angular-bootstrap/pagination/pagination.html deleted file mode 100755 index cd45d290d5142..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/pagination/pagination.html +++ /dev/null @@ -1,7 +0,0 @@ - \ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/pagination/pagination.js b/src/legacy/ui/public/angular-bootstrap/pagination/pagination.js deleted file mode 100755 index dee4bbb2199f0..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/pagination/pagination.js +++ /dev/null @@ -1,228 +0,0 @@ -import { i18n } from '@kbn/i18n'; - -angular.module('ui.bootstrap.pagination', []) - -.controller('PaginationController', ['$scope', '$attrs', '$parse', function ($scope, $attrs, $parse) { - var self = this, - ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl - setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; - - this.init = function(ngModelCtrl_, config) { - ngModelCtrl = ngModelCtrl_; - this.config = config; - - ngModelCtrl.$render = function() { - self.render(); - }; - - if ($attrs.itemsPerPage) { - $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { - self.itemsPerPage = parseInt(value, 10); - $scope.totalPages = self.calculateTotalPages(); - }); - } else { - this.itemsPerPage = config.itemsPerPage; - } - }; - - this.calculateTotalPages = function() { - var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); - return Math.max(totalPages || 0, 1); - }; - - this.render = function() { - $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1; - }; - - $scope.selectPage = function(page) { - if ( $scope.page !== page && page > 0 && page <= $scope.totalPages) { - ngModelCtrl.$setViewValue(page); - ngModelCtrl.$render(); - } - }; - - $scope.getText = function( key ) { - return $scope[key + 'Text'] || self.config[key + 'Text']; - }; - $scope.noPrevious = function() { - return $scope.page === 1; - }; - $scope.noNext = function() { - return $scope.page === $scope.totalPages; - }; - - $scope.$watch('totalItems', function() { - $scope.totalPages = self.calculateTotalPages(); - }); - - $scope.$watch('totalPages', function(value) { - setNumPages($scope.$parent, value); // Readonly variable - - if ( $scope.page > value ) { - $scope.selectPage(value); - } else { - ngModelCtrl.$render(); - } - }); -}]) - -.constant('paginationConfig', { - itemsPerPage: 10, - boundaryLinks: false, - directionLinks: true, - firstText: i18n.translate('common.ui.angularBootstrap.pagination.paginationConfig.firstLabel', { - defaultMessage: 'First' - }), - previousText: i18n.translate('common.ui.angularBootstrap.pagination.paginationConfig.previousLabel', { - defaultMessage: 'Previous' - }), - nextText: i18n.translate('common.ui.angularBootstrap.pagination.paginationConfig.nextLabel', { - defaultMessage: 'Next' - }), - lastText: i18n.translate('common.ui.angularBootstrap.pagination.paginationConfig.lastLabel', { - defaultMessage: 'Last' - }), - rotate: true -}) - -.directive('pagination', ['$parse', 'paginationConfig', function($parse, paginationConfig) { - return { - restrict: 'EA', - scope: { - totalItems: '=', - firstText: '@', - previousText: '@', - nextText: '@', - lastText: '@' - }, - require: ['pagination', '?ngModel'], - controller: 'PaginationController', - templateUrl: 'template/pagination/pagination.html', - replace: true, - link: function(scope, element, attrs, ctrls) { - var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - - if (!ngModelCtrl) { - return; // do nothing if no ng-model - } - - // Setup configuration parameters - var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize, - rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate; - scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks; - scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks; - - paginationCtrl.init(ngModelCtrl, paginationConfig); - - if (attrs.maxSize) { - scope.$parent.$watch($parse(attrs.maxSize), function(value) { - maxSize = parseInt(value, 10); - paginationCtrl.render(); - }); - } - - // Create page object used in template - function makePage(number, text, isActive) { - return { - number: number, - text: text, - active: isActive - }; - } - - function getPages(currentPage, totalPages) { - var pages = []; - - // Default page limits - var startPage = 1, endPage = totalPages; - var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); - - // recompute if maxSize - if ( isMaxSized ) { - if ( rotate ) { - // Current page is displayed in the middle of the visible ones - startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); - endPage = startPage + maxSize - 1; - - // Adjust if limit is exceeded - if (endPage > totalPages) { - endPage = totalPages; - startPage = endPage - maxSize + 1; - } - } else { - // Visible pages are paginated with maxSize - startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; - - // Adjust last page if limit is exceeded - endPage = Math.min(startPage + maxSize - 1, totalPages); - } - } - - // Add page number links - for (var number = startPage; number <= endPage; number++) { - var page = makePage(number, number, number === currentPage); - pages.push(page); - } - - // Add links to move between page sets - if ( isMaxSized && ! rotate ) { - if ( startPage > 1 ) { - var previousPageSet = makePage(startPage - 1, '...', false); - pages.unshift(previousPageSet); - } - - if ( endPage < totalPages ) { - var nextPageSet = makePage(endPage + 1, '...', false); - pages.push(nextPageSet); - } - } - - return pages; - } - - var originalRender = paginationCtrl.render; - paginationCtrl.render = function() { - originalRender(); - if (scope.page > 0 && scope.page <= scope.totalPages) { - scope.pages = getPages(scope.page, scope.totalPages); - } - }; - } - }; -}]) - -.constant('pagerConfig', { - itemsPerPage: 10, - previousText: i18n.translate('common.ui.angularBootstrap.pagination.pagerConfig.previousLabel', { - defaultMessage: '« Previous' - }), - nextText: i18n.translate('common.ui.angularBootstrap.pagination.pagerConfig.nextLabel', { - defaultMessage: 'Next »' - }), - align: true -}) - -.directive('pager', ['pagerConfig', function(pagerConfig) { - return { - restrict: 'EA', - scope: { - totalItems: '=', - previousText: '@', - nextText: '@' - }, - require: ['pager', '?ngModel'], - controller: 'PaginationController', - templateUrl: 'template/pagination/pager.html', - replace: true, - link: function(scope, element, attrs, ctrls) { - var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - - if (!ngModelCtrl) { - return; // do nothing if no ng-model - } - - scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align; - paginationCtrl.init(ngModelCtrl, pagerConfig); - } - }; -}]); diff --git a/src/legacy/ui/public/angular-bootstrap/progressbar/bar.html b/src/legacy/ui/public/angular-bootstrap/progressbar/bar.html old mode 100755 new mode 100644 index bde46dca5515f..069ae2f938cb2 --- a/src/legacy/ui/public/angular-bootstrap/progressbar/bar.html +++ b/src/legacy/ui/public/angular-bootstrap/progressbar/bar.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.js b/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.js index 9a6a6355d78b3..1bd18b0429b96 100755 --- a/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.js +++ b/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.js @@ -34,33 +34,33 @@ angular.module('ui.bootstrap.progressbar', []) }; }]) -.directive('progress', function() { - return { - restrict: 'EA', - replace: true, - transclude: true, - controller: 'ProgressController', - require: 'progress', - scope: {}, - templateUrl: 'template/progressbar/progress.html' - }; -}) +.directive('progress', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + require: 'progress', + scope: {}, + templateUrl: 'template/progressbar/progress.html' + }; +}) -.directive('bar', function() { - return { - restrict: 'EA', - replace: true, - transclude: true, - require: '^progress', - scope: { - value: '=', - type: '@' - }, - templateUrl: 'template/progressbar/bar.html', - link: function(scope, element, attrs, progressCtrl) { - progressCtrl.addBar(scope, element); - } - }; +.directive('bar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + require: '^progress', + scope: { + value: '=', + type: '@' + }, + templateUrl: 'template/progressbar/bar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, element); + } + }; }) .directive('progressbar', function() { diff --git a/src/legacy/ui/public/angular-bootstrap/timepicker/timepicker.html b/src/legacy/ui/public/angular-bootstrap/timepicker/timepicker.html deleted file mode 100755 index dabca515438b8..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/timepicker/timepicker.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - -
 
- - : - -
 
diff --git a/src/legacy/ui/public/angular-bootstrap/timepicker/timepicker.js b/src/legacy/ui/public/angular-bootstrap/timepicker/timepicker.js deleted file mode 100755 index 91ac86bcee3ff..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/timepicker/timepicker.js +++ /dev/null @@ -1,254 +0,0 @@ -angular.module('ui.bootstrap.timepicker', []) - -.constant('timepickerConfig', { - hourStep: 1, - minuteStep: 1, - showMeridian: true, - meridians: null, - readonlyInput: false, - mousewheel: true -}) - -.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) { - var selected = new Date(), - ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl - meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; - - this.init = function( ngModelCtrl_, inputs ) { - ngModelCtrl = ngModelCtrl_; - ngModelCtrl.$render = this.render; - - var hoursInputEl = inputs.eq(0), - minutesInputEl = inputs.eq(1); - - var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; - if ( mousewheel ) { - this.setupMousewheelEvents( hoursInputEl, minutesInputEl ); - } - - $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput; - this.setupInputEvents( hoursInputEl, minutesInputEl ); - }; - - var hourStep = timepickerConfig.hourStep; - if ($attrs.hourStep) { - $scope.$parent.$watch($parse($attrs.hourStep), function(value) { - hourStep = parseInt(value, 10); - }); - } - - var minuteStep = timepickerConfig.minuteStep; - if ($attrs.minuteStep) { - $scope.$parent.$watch($parse($attrs.minuteStep), function(value) { - minuteStep = parseInt(value, 10); - }); - } - - // 12H / 24H mode - $scope.showMeridian = timepickerConfig.showMeridian; - if ($attrs.showMeridian) { - $scope.$parent.$watch($parse($attrs.showMeridian), function(value) { - $scope.showMeridian = !!value; - - if ( ngModelCtrl.$error.time ) { - // Evaluate from template - var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); - if (angular.isDefined( hours ) && angular.isDefined( minutes )) { - selected.setHours( hours ); - refresh(); - } - } else { - updateTemplate(); - } - }); - } - - // Get $scope.hours in 24H mode if valid - function getHoursFromTemplate ( ) { - var hours = parseInt( $scope.hours, 10 ); - var valid = ( $scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24); - if ( !valid ) { - return undefined; - } - - if ( $scope.showMeridian ) { - if ( hours === 12 ) { - hours = 0; - } - if ( $scope.meridian === meridians[1] ) { - hours = hours + 12; - } - } - return hours; - } - - function getMinutesFromTemplate() { - var minutes = parseInt($scope.minutes, 10); - return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined; - } - - function pad( value ) { - return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value; - } - - // Respond on mousewheel spin - this.setupMousewheelEvents = function( hoursInputEl, minutesInputEl ) { - var isScrollingUp = function(e) { - if (e.originalEvent) { - e = e.originalEvent; - } - //pick correct delta variable depending on event - var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY; - return (e.detail || delta > 0); - }; - - hoursInputEl.bind('mousewheel wheel', function(e) { - $scope.$apply( (isScrollingUp(e)) ? $scope.incrementHours() : $scope.decrementHours() ); - e.preventDefault(); - }); - - minutesInputEl.bind('mousewheel wheel', function(e) { - $scope.$apply( (isScrollingUp(e)) ? $scope.incrementMinutes() : $scope.decrementMinutes() ); - e.preventDefault(); - }); - - }; - - this.setupInputEvents = function( hoursInputEl, minutesInputEl ) { - if ( $scope.readonlyInput ) { - $scope.updateHours = angular.noop; - $scope.updateMinutes = angular.noop; - return; - } - - var invalidate = function(invalidHours, invalidMinutes) { - ngModelCtrl.$setViewValue( null ); - ngModelCtrl.$setValidity('time', false); - if (angular.isDefined(invalidHours)) { - $scope.invalidHours = invalidHours; - } - if (angular.isDefined(invalidMinutes)) { - $scope.invalidMinutes = invalidMinutes; - } - }; - - $scope.updateHours = function() { - var hours = getHoursFromTemplate(); - - if ( angular.isDefined(hours) ) { - selected.setHours( hours ); - refresh( 'h' ); - } else { - invalidate(true); - } - }; - - hoursInputEl.bind('blur', function(e) { - if ( !$scope.invalidHours && $scope.hours < 10) { - $scope.$apply( function() { - $scope.hours = pad( $scope.hours ); - }); - } - }); - - $scope.updateMinutes = function() { - var minutes = getMinutesFromTemplate(); - - if ( angular.isDefined(minutes) ) { - selected.setMinutes( minutes ); - refresh( 'm' ); - } else { - invalidate(undefined, true); - } - }; - - minutesInputEl.bind('blur', function(e) { - if ( !$scope.invalidMinutes && $scope.minutes < 10 ) { - $scope.$apply( function() { - $scope.minutes = pad( $scope.minutes ); - }); - } - }); - - }; - - this.render = function() { - var date = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : null; - - if ( isNaN(date) ) { - ngModelCtrl.$setValidity('time', false); - $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); - } else { - if ( date ) { - selected = date; - } - makeValid(); - updateTemplate(); - } - }; - - // Call internally when we know that model is valid. - function refresh( keyboardChange ) { - makeValid(); - ngModelCtrl.$setViewValue( new Date(selected) ); - updateTemplate( keyboardChange ); - } - - function makeValid() { - ngModelCtrl.$setValidity('time', true); - $scope.invalidHours = false; - $scope.invalidMinutes = false; - } - - function updateTemplate( keyboardChange ) { - var hours = selected.getHours(), minutes = selected.getMinutes(); - - if ( $scope.showMeridian ) { - hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system - } - - $scope.hours = keyboardChange === 'h' ? hours : pad(hours); - $scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes); - $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; - } - - function addMinutes( minutes ) { - var dt = new Date( selected.getTime() + minutes * 60000 ); - selected.setHours( dt.getHours(), dt.getMinutes() ); - refresh(); - } - - $scope.incrementHours = function() { - addMinutes( hourStep * 60 ); - }; - $scope.decrementHours = function() { - addMinutes( - hourStep * 60 ); - }; - $scope.incrementMinutes = function() { - addMinutes( minuteStep ); - }; - $scope.decrementMinutes = function() { - addMinutes( - minuteStep ); - }; - $scope.toggleMeridian = function() { - addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) ); - }; -}]) - -.directive('timepicker', function () { - return { - restrict: 'EA', - require: ['timepicker', '?^ngModel'], - controller:'TimepickerController', - replace: true, - scope: {}, - templateUrl: 'template/timepicker/timepicker.html', - link: function(scope, element, attrs, ctrls) { - var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - - if ( ngModelCtrl ) { - timepickerCtrl.init( ngModelCtrl, element.find('input') ); - } - } - }; -}); diff --git a/src/legacy/ui/public/angular-bootstrap/position/position.js b/src/legacy/ui/public/angular-bootstrap/tooltip/position.js similarity index 100% rename from src/legacy/ui/public/angular-bootstrap/position/position.js rename to src/legacy/ui/public/angular-bootstrap/tooltip/position.js diff --git a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-html-unsafe-popup.html b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-html-unsafe-popup.html old mode 100755 new mode 100644 index 8203297276be9..b48bf70498906 --- a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-html-unsafe-popup.html +++ b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-html-unsafe-popup.html @@ -1,4 +1,4 @@ -
-
-
-
+
+
+
+
\ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html old mode 100755 new mode 100644 index b464bbb0f3090..eed4ca7d93016 --- a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html +++ b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html @@ -1,4 +1,4 @@ -
-
-
-
+
+
+
+
\ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip.js b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip.js index 94199dadb8dbd..b59b2922d8089 100755 --- a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip.js +++ b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip.js @@ -1,9 +1,11 @@ +import './position'; + /** * The following features are still outstanding: animation as a * function, placement as a function, inside, support for more triggers than * just mouse enter/leave, html tooltips, and selector delegation. */ -angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) +angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position' ] ) /** * The $tooltip service creates tooltip- and popover-like directives as well as @@ -345,28 +347,28 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap }]; }) -.directive( 'tooltipPopup', function () { - return { - restrict: 'EA', - replace: true, - scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, - templateUrl: 'template/tooltip/tooltip-popup.html' - }; -}) - .directive( 'tooltip', [ '$tooltip', function ( $tooltip ) { return $tooltip( 'tooltip', 'tooltip', 'mouseenter' ); }]) -.directive( 'tooltipHtmlUnsafePopup', function () { - return { - restrict: 'EA', - replace: true, - scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, - templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html' - }; +.directive( 'tooltipPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-popup.html' + }; }) .directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) { return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' ); -}]); +}]) + +.directive( 'tooltipHtmlUnsafePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html' + }; +}); \ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-match.html b/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-match.html deleted file mode 100755 index d79e10a18f8a0..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-match.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-popup.html b/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-popup.html deleted file mode 100755 index e1bd0c1c476d8..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-popup.html +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead.js b/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead.js deleted file mode 100755 index 53d7162da84b2..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead.js +++ /dev/null @@ -1,398 +0,0 @@ -angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml']) - -/** - * A helper service that can parse typeahead's syntax (string provided by users) - * Extracted to a separate service for ease of unit testing - */ - .factory('typeaheadParser', ['$parse', function ($parse) { - - // 00000111000000000000022200000000000000003333333333333330000000000044000 - var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; - - return { - parse:function (input) { - - var match = input.match(TYPEAHEAD_REGEXP); - if (!match) { - throw new Error( - 'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + - ' but got "' + input + '".'); - } - - return { - itemName:match[3], - source:$parse(match[4]), - viewMapper:$parse(match[2] || match[1]), - modelMapper:$parse(match[1]) - }; - } - }; -}]) - - .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', - function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { - - var HOT_KEYS = [9, 13, 27, 38, 40]; - - return { - require:'ngModel', - link:function (originalScope, element, attrs, modelCtrl) { - - //SUPPORTED ATTRIBUTES (OPTIONS) - - //minimal no of characters that needs to be entered before typeahead kicks-in - var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1; - - //minimal wait time after last character typed before typehead kicks-in - var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; - - //should it restrict model values to the ones selected from the popup only? - var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; - - //binding to a variable that indicates if matches are being retrieved asynchronously - var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; - - //a callback executed when a match is selected - var onSelectCallback = $parse(attrs.typeaheadOnSelect); - - var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; - - var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; - - var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; - - //INTERNAL VARIABLES - - //model setter executed upon match selection - var $setModelValue = $parse(attrs.ngModel).assign; - - //expressions used by typeahead - var parserResult = typeaheadParser.parse(attrs.typeahead); - - var hasFocus; - - //create a child scope for the typeahead directive so we are not polluting original scope - //with typeahead-specific data (matches, query etc.) - var scope = originalScope.$new(); - originalScope.$on('$destroy', function(){ - scope.$destroy(); - }); - - // WAI-ARIA - var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000); - element.attr({ - 'aria-autocomplete': 'list', - 'aria-expanded': false, - 'aria-owns': popupId - }); - - //pop-up element used to display matches - var popUpEl = angular.element('
'); - popUpEl.attr({ - id: popupId, - matches: 'matches', - active: 'activeIdx', - select: 'select(activeIdx)', - query: 'query', - position: 'position' - }); - //custom item template - if (angular.isDefined(attrs.typeaheadTemplateUrl)) { - popUpEl.attr('template-url', attrs.typeaheadTemplateUrl); - } - - var resetMatches = function() { - scope.matches = []; - scope.activeIdx = -1; - element.attr('aria-expanded', false); - }; - - var getMatchId = function(index) { - return popupId + '-option-' + index; - }; - - // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead. - // This attribute is added or removed automatically when the `activeIdx` changes. - scope.$watch('activeIdx', function(index) { - if (index < 0) { - element.removeAttr('aria-activedescendant'); - } else { - element.attr('aria-activedescendant', getMatchId(index)); - } - }); - - var getMatchesAsync = function(inputValue) { - - var locals = {$viewValue: inputValue}; - isLoadingSetter(originalScope, true); - $q.when(parserResult.source(originalScope, locals)).then(function(matches) { - - //it might happen that several async queries were in progress if a user were typing fast - //but we are interested only in responses that correspond to the current view value - var onCurrentRequest = (inputValue === modelCtrl.$viewValue); - if (onCurrentRequest && hasFocus) { - if (matches.length > 0) { - - scope.activeIdx = focusFirst ? 0 : -1; - scope.matches.length = 0; - - //transform labels - for(var i=0; i= minSearch) { - if (waitTime > 0) { - cancelPreviousTimeout(); - scheduleSearchWithTimeout(inputValue); - } else { - getMatchesAsync(inputValue); - } - } else { - isLoadingSetter(originalScope, false); - cancelPreviousTimeout(); - resetMatches(); - } - - if (isEditable) { - return inputValue; - } else { - if (!inputValue) { - // Reset in case user had typed something previously. - modelCtrl.$setValidity('editable', true); - return inputValue; - } else { - modelCtrl.$setValidity('editable', false); - return undefined; - } - } - }); - - modelCtrl.$formatters.push(function (modelValue) { - - var candidateViewValue, emptyViewValue; - var locals = {}; - - if (inputFormatter) { - - locals.$model = modelValue; - return inputFormatter(originalScope, locals); - - } else { - - //it might happen that we don't have enough info to properly render input value - //we need to check for this situation and simply return model value if we can't apply custom formatting - locals[parserResult.itemName] = modelValue; - candidateViewValue = parserResult.viewMapper(originalScope, locals); - locals[parserResult.itemName] = undefined; - emptyViewValue = parserResult.viewMapper(originalScope, locals); - - return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; - } - }); - - scope.select = function (activeIdx) { - //called from within the $digest() cycle - var locals = {}; - var model, item; - - locals[parserResult.itemName] = item = scope.matches[activeIdx].model; - model = parserResult.modelMapper(originalScope, locals); - $setModelValue(originalScope, model); - modelCtrl.$setValidity('editable', true); - - onSelectCallback(originalScope, { - $item: item, - $model: model, - $label: parserResult.viewMapper(originalScope, locals) - }); - - resetMatches(); - - //return focus to the input element if a match was selected via a mouse click event - // use timeout to avoid $rootScope:inprog error - $timeout(function() { element[0].focus(); }, 0, false); - }; - - //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27) - element.bind('keydown', function (evt) { - - //typeahead is open and an "interesting" key was pressed - if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { - return; - } - - // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything - if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) { - return; - } - - evt.preventDefault(); - - if (evt.which === 40) { - scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; - scope.$digest(); - - } else if (evt.which === 38) { - scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; - scope.$digest(); - - } else if (evt.which === 13 || evt.which === 9) { - scope.$apply(function () { - scope.select(scope.activeIdx); - }); - - } else if (evt.which === 27) { - evt.stopPropagation(); - - resetMatches(); - scope.$digest(); - } - }); - - element.bind('blur', function (evt) { - hasFocus = false; - }); - - // Keep reference to click handler to unbind it. - var dismissClickHandler = function (evt) { - if (element[0] !== evt.target) { - resetMatches(); - scope.$digest(); - } - }; - - $document.bind('click', dismissClickHandler); - - originalScope.$on('$destroy', function(){ - $document.unbind('click', dismissClickHandler); - if (appendToBody) { - $popup.remove(); - } - }); - - var $popup = $compile(popUpEl)(scope); - if (appendToBody) { - $document.find('body').append($popup); - } else { - element.after($popup); - } - } - }; - -}]) - - .directive('typeaheadPopup', function () { - return { - restrict:'EA', - scope:{ - matches:'=', - query:'=', - active:'=', - position:'=', - select:'&' - }, - replace:true, - templateUrl:'template/typeahead/typeahead-popup.html', - link:function (scope, element, attrs) { - - scope.templateUrl = attrs.templateUrl; - - scope.isOpen = function () { - return scope.matches.length > 0; - }; - - scope.isActive = function (matchIdx) { - return scope.active == matchIdx; - }; - - scope.selectActive = function (matchIdx) { - scope.active = matchIdx; - }; - - scope.selectMatch = function (activeIdx) { - scope.select({activeIdx:activeIdx}); - }; - } - }; - }) - - .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) { - return { - restrict:'EA', - scope:{ - index:'=', - match:'=', - query:'=' - }, - link:function (scope, element, attrs) { - var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html'; - $http.get(tplUrl, {cache: $templateCache}).then(function(resp){ - element.replaceWith($compile(resp.data.trim())(scope)); - }); - } - }; - }]) - - .filter('typeaheadHighlight', function() { - - function escapeRegexp(queryToEscape) { - return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); - } - - return function(matchItem, query) { - return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; - }; - }); diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 8f705fa69439d..a6866aa2dab68 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -264,13 +264,6 @@ "common.ui.aggTypes.sortOnTooltip": "排序依据", "common.ui.aggTypes.timeIntervalLabel": "时间间隔", "common.ui.aggTypes.valuesLabel": "值", - "common.ui.angularBootstrap.alert.closeButtonLabel": "关闭", - "common.ui.angularBootstrap.pagination.pagerConfig.nextLabel": "下一页 »", - "common.ui.angularBootstrap.pagination.pagerConfig.previousLabel": "« 上一页", - "common.ui.angularBootstrap.pagination.paginationConfig.firstLabel": "第一", - "common.ui.angularBootstrap.pagination.paginationConfig.lastLabel": "最后", - "common.ui.angularBootstrap.pagination.paginationConfig.nextLabel": "下一个", - "common.ui.angularBootstrap.pagination.paginationConfig.previousLabel": "上一个", "common.ui.chrome.bigUrlWarningNotificationMessage": "在“{advancedSettingsLink}”启用“{storeInSessionStorageParam}”选项,或简化屏幕视觉效果。", "common.ui.chrome.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高级设置", "common.ui.chrome.bigUrlWarningNotificationTitle": "URL 过大,Kibana 可能无法工作", From 6a2e22f512a5d71ca520abe3f2e98b3f0698110f Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Sun, 24 Mar 2019 12:56:42 +0200 Subject: [PATCH 18/96] Deleted bar, progress and progressbar directives (#33585) * Deleted - progress - bar - progressbar Changed - implementation of Discover > string field > proressbar to use EUI progressbar and tooltip. * added bug comment * Fixed CR --- .../field_chooser/_field_chooser.scss | 7 ++ .../field_chooser/discover_field.js | 1 + .../lib/detail_views/string.html | 13 +-- .../field_chooser/string_progress_bar.js | 70 ++++++++++++++++ .../ui/public/angular-bootstrap/index.js | 29 +------ .../angular-bootstrap/progressbar/bar.html | 1 - .../progressbar/progress.html | 1 - .../progressbar/progressbar.html | 3 - .../progressbar/progressbar.js | 81 ------------------- 9 files changed, 85 insertions(+), 121 deletions(-) create mode 100644 src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js delete mode 100644 src/legacy/ui/public/angular-bootstrap/progressbar/bar.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/progressbar/progress.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.html delete mode 100755 src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.js diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss index 65b26da9afa4c..fcc8de845c334 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss @@ -2,3 +2,10 @@ color: $euiColorMediumShade; margin-left: $euiSizeS !important; } + +/* + Fixes EUI known issue https://github.com/elastic/eui/issues/1749 +*/ +.dscProgressBarTooltip__anchor { + display: block; +} \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js index 66b8eb8ab6cd2..1f4b3103af7c1 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js @@ -22,6 +22,7 @@ import html from './discover_field.html'; import _ from 'lodash'; import 'ui/directives/css_truncate'; import 'ui/directives/field_name'; +import './string_progress_bar'; import detailsHtml from './lib/detail_views/string.html'; import { uiModules } from 'ui/modules'; const app = uiModules.get('apps/discover'); diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html index b0eb97ea5b62e..37786c3812ec5 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html @@ -77,15 +77,10 @@
- - - {{bucket.percent}}% - - +
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js new file mode 100644 index 0000000000000..ae00df6dfbbf8 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js @@ -0,0 +1,70 @@ +/* + * 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 { wrapInI18nContext } from 'ui/i18n'; +import { uiModules } from 'ui/modules'; + +import React from 'react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiProgress, + EuiText, + EuiToolTip, +} from '@elastic/eui'; + +const module = uiModules.get('discover/field_chooser'); + +function StringFieldProgressBar(props) { + return ( + + + + + + + + {props.percent}% + + + + + ); +} + +module.directive('stringFieldProgressBar', function (reactDirective) { + return reactDirective(wrapInI18nContext(StringFieldProgressBar)); +}); diff --git a/src/legacy/ui/public/angular-bootstrap/index.js b/src/legacy/ui/public/angular-bootstrap/index.js index 7378cf90e3708..c86da04f5bc41 100644 --- a/src/legacy/ui/public/angular-bootstrap/index.js +++ b/src/legacy/ui/public/angular-bootstrap/index.js @@ -26,22 +26,17 @@ angular.module('ui.bootstrap', [ 'ui.bootstrap.bindHtml', 'ui.bootstrap.modal', 'ui.bootstrap.tooltip', - 'ui.bootstrap.progressbar', ]); angular.module('ui.bootstrap.tpls', [ 'template/modal/backdrop.html', - 'template/modal/window.html', - 'template/tooltip/tooltip-html-unsafe-popup.html', - 'template/tooltip/tooltip-popup.html', - 'template/progressbar/bar.html', - 'template/progressbar/progress.html', - 'template/progressbar/progressbar.html', + 'template/modal/window.html', + 'template/tooltip/tooltip-html-unsafe-popup.html', + 'template/tooltip/tooltip-popup.html', ]); import './bindHtml/bindHtml'; import './modal/modal'; -import './progressbar/progressbar'; import './tooltip/tooltip'; import './transition/transition'; @@ -68,21 +63,3 @@ import tooltipPopup from './tooltip/tooltip-popup.html'; angular.module('template/tooltip/tooltip-popup.html', []).run(['$templateCache', function($templateCache) { $templateCache.put('template/tooltip/tooltip-popup.html', tooltipPopup); }]); - -import bar from './progressbar/bar.html'; - - angular.module('template/progressbar/bar.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/progressbar/bar.html', bar); -}]); - -import progress from './progressbar/progress.html'; - -angular.module('template/progressbar/progress.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/progressbar/progress.html', progress); -}]); - -import progressbar from './progressbar/progressbar.html'; - -angular.module('template/progressbar/progressbar.html', []).run(['$templateCache', function($templateCache) { - $templateCache.put('template/progressbar/progressbar.html', progressbar); -}]); diff --git a/src/legacy/ui/public/angular-bootstrap/progressbar/bar.html b/src/legacy/ui/public/angular-bootstrap/progressbar/bar.html deleted file mode 100644 index 069ae2f938cb2..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/progressbar/bar.html +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/progressbar/progress.html b/src/legacy/ui/public/angular-bootstrap/progressbar/progress.html deleted file mode 100755 index 1968537006087..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/progressbar/progress.html +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.html b/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.html deleted file mode 100755 index efb6503302e32..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.html +++ /dev/null @@ -1,3 +0,0 @@ -
-
-
\ No newline at end of file diff --git a/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.js b/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.js deleted file mode 100755 index 1bd18b0429b96..0000000000000 --- a/src/legacy/ui/public/angular-bootstrap/progressbar/progressbar.js +++ /dev/null @@ -1,81 +0,0 @@ -angular.module('ui.bootstrap.progressbar', []) - -.constant('progressConfig', { - animate: true, - max: 100 -}) - -.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) { - var self = this, - animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; - - this.bars = []; - $scope.max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max; - - this.addBar = function(bar, element) { - if ( !animate ) { - element.css({'transition': 'none'}); - } - - this.bars.push(bar); - - bar.$watch('value', function( value ) { - bar.percent = +(100 * value / $scope.max).toFixed(2); - }); - - bar.$on('$destroy', function() { - element = null; - self.removeBar(bar); - }); - }; - - this.removeBar = function(bar) { - this.bars.splice(this.bars.indexOf(bar), 1); - }; -}]) - -.directive('progress', function() { - return { - restrict: 'EA', - replace: true, - transclude: true, - controller: 'ProgressController', - require: 'progress', - scope: {}, - templateUrl: 'template/progressbar/progress.html' - }; -}) - -.directive('bar', function() { - return { - restrict: 'EA', - replace: true, - transclude: true, - require: '^progress', - scope: { - value: '=', - type: '@' - }, - templateUrl: 'template/progressbar/bar.html', - link: function(scope, element, attrs, progressCtrl) { - progressCtrl.addBar(scope, element); - } - }; -}) - -.directive('progressbar', function() { - return { - restrict: 'EA', - replace: true, - transclude: true, - controller: 'ProgressController', - scope: { - value: '=', - type: '@' - }, - templateUrl: 'template/progressbar/progressbar.html', - link: function(scope, element, attrs, progressCtrl) { - progressCtrl.addBar(scope, angular.element(element.children()[0])); - } - }; -}); \ No newline at end of file From 657552d88853f750666a28f1945f21ce0acd33d4 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Mon, 25 Mar 2019 05:30:30 -0300 Subject: [PATCH 19/96] Allow editing editorState in data panel (#33305) --- src/legacy/ui/public/vis/editors/default/agg_group.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/legacy/ui/public/vis/editors/default/agg_group.js b/src/legacy/ui/public/vis/editors/default/agg_group.js index 015a259f209c1..b8fbb716ba1e1 100644 --- a/src/legacy/ui/public/vis/editors/default/agg_group.js +++ b/src/legacy/ui/public/vis/editors/default/agg_group.js @@ -39,6 +39,12 @@ uiModules $scope.groupNameLabel = aggGroupNameMaps()[$scope.groupName]; $scope.$bind('group', 'state.aggs.bySchemaGroup["' + $scope.groupName + '"]'); $scope.$bind('schemas', 'vis.type.schemas["' + $scope.groupName + '"]'); + // We use `editorState` to access the state of the editor in the options panels. + // There are some aggregations (dot size metric) that needs to set parameters on the + // editorState too. Since we have the editor state here available as `state`, we're just + // binding it to the same name `editorState` so the controls look the same if they are in + // the data tab or within any other options tab. + $scope.$bind('editorState', 'state'); $scope.$watchMulti([ 'schemas', From 78fac18d47a66fda39f8198c51f2544191b37999 Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Mon, 25 Mar 2019 15:12:11 +0100 Subject: [PATCH 20/96] Remove *Module classes that wrap services (#33698) * Remove *Module classes that wrapped services * Fix tests * Remove empty core/server README --- src/core/server/README.md | 6 --- src/core/server/elasticsearch/index.ts | 14 +------ src/core/server/http/index.ts | 24 +----------- src/core/server/legacy/index.ts | 12 ------ src/core/server/plugins/index.ts | 12 +----- src/core/server/server.ts | 54 +++++++++++++++----------- src/test_utils/kbn_server.ts | 4 +- 7 files changed, 38 insertions(+), 88 deletions(-) delete mode 100644 src/core/server/README.md diff --git a/src/core/server/README.md b/src/core/server/README.md deleted file mode 100644 index 53807c4f036b8..0000000000000 --- a/src/core/server/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Platform Server Modules -======================= - -Http Server ------------ -TODO: explain diff --git a/src/core/server/elasticsearch/index.ts b/src/core/server/elasticsearch/index.ts index aeb490b42db2f..cc35c9b75e32c 100644 --- a/src/core/server/elasticsearch/index.ts +++ b/src/core/server/elasticsearch/index.ts @@ -17,17 +17,5 @@ * under the License. */ -export { ElasticsearchServiceSetup } from './elasticsearch_service'; +export { ElasticsearchServiceSetup, ElasticsearchService } from './elasticsearch_service'; export { CallAPIOptions, ClusterClient } from './cluster_client'; - -import { CoreContext } from '../core_context'; -import { ElasticsearchService } from './elasticsearch_service'; - -/** @internal */ -export class ElasticsearchModule { - public readonly service: ElasticsearchService; - - constructor(coreContext: CoreContext) { - this.service = new ElasticsearchService(coreContext); - } -} diff --git a/src/core/server/http/index.ts b/src/core/server/http/index.ts index a1385b1b7bf91..2c0dbf2488373 100644 --- a/src/core/server/http/index.ts +++ b/src/core/server/http/index.ts @@ -17,28 +17,8 @@ * under the License. */ -import { Observable } from 'rxjs'; - -import { LoggerFactory } from '../logging'; -import { HttpConfig } from './http_config'; -import { HttpService, HttpServiceSetup } from './http_service'; -import { Router } from './router'; - +export { HttpConfig } from './http_config'; +export { HttpService, HttpServiceSetup } from './http_service'; export { Router, KibanaRequest } from './router'; -export { HttpService, HttpServiceSetup }; export { HttpServerInfo } from './http_server'; export { BasePathProxyServer } from './base_path_proxy_server'; - -export { HttpConfig }; - -export class HttpModule { - public readonly service: HttpService; - - constructor(readonly config$: Observable, logger: LoggerFactory) { - this.service = new HttpService(this.config$, logger); - - const router = new Router('/core'); - router.get({ path: '/', validate: false }, async (req, res) => res.ok({ version: '0.0.1' })); - this.service.registerRouter(router); - } -} diff --git a/src/core/server/legacy/index.ts b/src/core/server/legacy/index.ts index 429e54ef673d4..bb965c0272d14 100644 --- a/src/core/server/legacy/index.ts +++ b/src/core/server/legacy/index.ts @@ -17,19 +17,7 @@ * under the License. */ -import { CoreContext } from '../core_context'; -import { LegacyService } from './legacy_service'; - /** @internal */ export { LegacyObjectToConfigAdapter } from './config/legacy_object_to_config_adapter'; /** @internal */ export { LegacyService } from './legacy_service'; - -/** @internal */ -export class LegacyCompatModule { - public readonly service: LegacyService; - - constructor(coreContext: CoreContext) { - this.service = new LegacyService(coreContext); - } -} diff --git a/src/core/server/plugins/index.ts b/src/core/server/plugins/index.ts index 7b3c680a90018..69a0a8ae1dcdf 100644 --- a/src/core/server/plugins/index.ts +++ b/src/core/server/plugins/index.ts @@ -17,8 +17,7 @@ * under the License. */ -import { CoreContext } from '../core_context'; -import { PluginsService } from './plugins_service'; +export { PluginsService } from './plugins_service'; /** @internal */ export { isNewPlatformPlugin } from './discovery'; @@ -26,12 +25,3 @@ export { isNewPlatformPlugin } from './discovery'; export { DiscoveredPlugin, DiscoveredPluginInternal } from './plugin'; export { PluginName } from './plugin'; export { PluginInitializerContext, PluginSetupContext } from './plugin_context'; - -/** @internal */ -export class PluginsModule { - public readonly service: PluginsService; - - constructor(coreContext: CoreContext) { - this.service = new PluginsService(coreContext); - } -} diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 51cebd8365570..26be718bf2d65 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -19,28 +19,35 @@ import { first } from 'rxjs/operators'; import { ConfigService, Env } from './config'; -import { ElasticsearchModule } from './elasticsearch'; -import { HttpConfig, HttpModule, HttpServiceSetup } from './http'; -import { LegacyCompatModule } from './legacy'; +import { ElasticsearchService } from './elasticsearch'; +import { HttpConfig, HttpService, HttpServiceSetup, Router } from './http'; +import { LegacyService } from './legacy'; import { Logger, LoggerFactory } from './logging'; -import { PluginsModule } from './plugins'; +import { PluginsService } from './plugins'; export class Server { - private readonly elasticsearch: ElasticsearchModule; - private readonly http: HttpModule; - private readonly plugins: PluginsModule; - private readonly legacy: LegacyCompatModule; + private readonly elasticsearch: ElasticsearchService; + private readonly http: HttpService; + private readonly plugins: PluginsService; + private readonly legacy: LegacyService; private readonly log: Logger; - constructor(configService: ConfigService, logger: LoggerFactory, private readonly env: Env) { + constructor( + private readonly configService: ConfigService, + logger: LoggerFactory, + private readonly env: Env + ) { this.log = logger.get('server'); - this.http = new HttpModule(configService.atPath('server', HttpConfig), logger); + this.http = new HttpService(configService.atPath('server', HttpConfig), logger); + const router = new Router('/core'); + router.get({ path: '/', validate: false }, async (req, res) => res.ok({ version: '0.0.1' })); + this.http.registerRouter(router); const core = { env, configService, logger }; - this.plugins = new PluginsModule(core); - this.legacy = new LegacyCompatModule(core); - this.elasticsearch = new ElasticsearchModule(core); + this.plugins = new PluginsService(core); + this.legacy = new LegacyService(core); + this.elasticsearch = new ElasticsearchService(core); } public async setup() { @@ -51,18 +58,21 @@ export class Server { // 2. When the process is run as dev cluster master in which case cluster manager // will fork a dedicated process where http service will be set up instead. let httpSetup: HttpServiceSetup | undefined; - const httpConfig = await this.http.config$.pipe(first()).toPromise(); + const httpConfig = await this.configService + .atPath('server', HttpConfig) + .pipe(first()) + .toPromise(); if (!this.env.isDevClusterMaster && httpConfig.autoListen) { - httpSetup = await this.http.service.setup(); + httpSetup = await this.http.setup(); } - const elasticsearchServiceSetup = await this.elasticsearch.service.setup(); + const elasticsearchServiceSetup = await this.elasticsearch.setup(); - const pluginsSetup = await this.plugins.service.setup({ + const pluginsSetup = await this.plugins.setup({ elasticsearch: elasticsearchServiceSetup, }); - await this.legacy.service.setup({ + await this.legacy.setup({ elasticsearch: elasticsearchServiceSetup, http: httpSetup, plugins: pluginsSetup, @@ -72,9 +82,9 @@ export class Server { public async stop() { this.log.debug('stopping server'); - await this.legacy.service.stop(); - await this.plugins.service.stop(); - await this.elasticsearch.service.stop(); - await this.http.service.stop(); + await this.legacy.stop(); + await this.plugins.stop(); + await this.elasticsearch.stop(); + await this.http.stop(); } } diff --git a/src/test_utils/kbn_server.ts b/src/test_utils/kbn_server.ts index e5f63d73e9a60..5326b11852354 100644 --- a/src/test_utils/kbn_server.ts +++ b/src/test_utils/kbn_server.ts @@ -92,7 +92,7 @@ export function createRootWithSettings(...settings: Array>) */ function getSupertest(root: Root, method: HttpMethod, path: string) { const testUserCredentials = Buffer.from(`${kibanaTestUser.username}:${kibanaTestUser.password}`); - return supertest((root as any).server.http.service.httpServer.server.listener) + return supertest((root as any).server.http.httpServer.server.listener) [method](path) .set('Authorization', `Basic ${testUserCredentials.toString('base64')}`); } @@ -124,7 +124,7 @@ export function createRootWithCorePlugins(settings = {}) { * @param root */ export function getKbnServer(root: Root) { - return (root as any).server.legacy.service.kbnServer; + return (root as any).server.legacy.kbnServer; } export const request: Record< From c6699c79862e5890895d2997dfd37df4011f782d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20=C3=81lvarez?= Date: Mon, 25 Mar 2019 15:55:24 +0100 Subject: [PATCH 21/96] update kibana index pattern for APM (#33778) --- .../server/tutorials/apm/saved_objects/index_pattern.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/saved_objects/index_pattern.json b/src/legacy/core_plugins/kibana/server/tutorials/apm/saved_objects/index_pattern.json index 2fbb87fa2e19e..0f681b4c79bb7 100644 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/saved_objects/index_pattern.json +++ b/src/legacy/core_plugins/kibana/server/tutorials/apm/saved_objects/index_pattern.json @@ -1,7 +1,7 @@ { "attributes": { - "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"destination.bytes\":{\"id\":\"bytes\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\"}},\"file.size\":{\"id\":\"bytes\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"network.bytes\":{\"id\":\"bytes\"},\"server.bytes\":{\"id\":\"bytes\"},\"source.bytes\":{\"id\":\"bytes\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", - "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", + "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"destination.bytes\":{\"id\":\"bytes\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\"}},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"network.bytes\":{\"id\":\"bytes\"},\"server.bytes\":{\"id\":\"bytes\"},\"source.bytes\":{\"id\":\"bytes\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", + "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", "sourceFilters": "[{\"value\":\"sourcemap.sourcemap\"}]", "timeFieldName": "@timestamp" }, From 8aa8c55002a343adf8d11a154a273f3c84241968 Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Mon, 25 Mar 2019 10:01:20 -0500 Subject: [PATCH 22/96] Rename `newPlatform.start` to `newPlatform.setup` in legacy (#33708) --- src/legacy/core_plugins/console/index.js | 2 +- src/legacy/core_plugins/elasticsearch/index.js | 8 ++++---- .../vis_data/__tests__/helpers/get_es_shard_timeout.js | 2 +- .../server/lib/vis_data/helpers/get_es_shard_timeout.js | 2 +- .../series_functions/__tests__/fixtures/tlConfig.js | 2 +- .../timelion/server/series_functions/es/index.js | 2 +- src/legacy/server/kbn_server.js | 2 +- src/legacy/ui/ui_render/ui_render_mixin.js | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/legacy/core_plugins/console/index.js b/src/legacy/core_plugins/console/index.js index 64d3c04db242c..652696bc7bfd8 100644 --- a/src/legacy/core_plugins/console/index.js +++ b/src/legacy/core_plugins/console/index.js @@ -103,7 +103,7 @@ export default function (kibana) { } const config = server.config(); - const legacyEsConfig = await server.newPlatform.start.core.elasticsearch.legacy.config$.pipe(first()).toPromise(); + const legacyEsConfig = await server.newPlatform.setup.core.elasticsearch.legacy.config$.pipe(first()).toPromise(); const proxyConfigCollection = new ProxyConfigCollection(options.proxyConfig); const proxyPathFilters = options.proxyFilter.map(str => new RegExp(str)); diff --git a/src/legacy/core_plugins/elasticsearch/index.js b/src/legacy/core_plugins/elasticsearch/index.js index 6abeceb300a0e..8dc9c77e79d99 100644 --- a/src/legacy/core_plugins/elasticsearch/index.js +++ b/src/legacy/core_plugins/elasticsearch/index.js @@ -36,9 +36,9 @@ export default function (kibana) { // value from all observables here to be able to synchronously return and create // cluster clients afterwards. const [esConfig, adminCluster, dataCluster] = await combineLatest( - server.newPlatform.start.core.elasticsearch.legacy.config$, - server.newPlatform.start.core.elasticsearch.adminClient$, - server.newPlatform.start.core.elasticsearch.dataClient$ + server.newPlatform.setup.core.elasticsearch.legacy.config$, + server.newPlatform.setup.core.elasticsearch.adminClient$, + server.newPlatform.setup.core.elasticsearch.dataClient$ ).pipe( first(), map(([config, adminClusterClient, dataClusterClient]) => [ @@ -80,7 +80,7 @@ export default function (kibana) { // We fill all the missing properties in the `clientConfig` using the default // Elasticsearch config so that we don't depend on default values set and // controlled by underlying Elasticsearch JS client. - const cluster = new Cluster(server.newPlatform.start.core.elasticsearch.createClient(name, { + const cluster = new Cluster(server.newPlatform.setup.core.elasticsearch.createClient(name, { ...esConfig, ...clientConfig, })); diff --git a/src/legacy/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js b/src/legacy/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js index a3174d0b2c6cf..123922ea6a563 100644 --- a/src/legacy/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js +++ b/src/legacy/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js @@ -27,7 +27,7 @@ describe('getEsShardTimeout', () => { const req = { server: { newPlatform: { - start: { + setup: { core: { elasticsearch: { legacy: { config$: of({ shardTimeout: moment.duration(12345) }) } } } diff --git a/src/legacy/core_plugins/metrics/server/lib/vis_data/helpers/get_es_shard_timeout.js b/src/legacy/core_plugins/metrics/server/lib/vis_data/helpers/get_es_shard_timeout.js index 7f3b8c157cda2..a49cc7a6de7c4 100644 --- a/src/legacy/core_plugins/metrics/server/lib/vis_data/helpers/get_es_shard_timeout.js +++ b/src/legacy/core_plugins/metrics/server/lib/vis_data/helpers/get_es_shard_timeout.js @@ -19,7 +19,7 @@ import { first, map } from 'rxjs/operators'; export async function getEsShardTimeout(req) { - return await req.server.newPlatform.start.core.elasticsearch.legacy.config$.pipe( + return await req.server.newPlatform.setup.core.elasticsearch.legacy.config$.pipe( first(), map(config => config.shardTimeout.asMilliseconds()) ).toPromise(); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js index aaabfc420031a..3ad6b0a549b87 100644 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js +++ b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js @@ -42,7 +42,7 @@ export default function () { } }, newPlatform: { - start: { + setup: { core: { elasticsearch: { legacy: { config$: of({ shardTimeout: moment.duration(30000) }) } diff --git a/src/legacy/core_plugins/timelion/server/series_functions/es/index.js b/src/legacy/core_plugins/timelion/server/series_functions/es/index.js index c38d1c2a4af44..1497b7e1953f9 100644 --- a/src/legacy/core_plugins/timelion/server/series_functions/es/index.js +++ b/src/legacy/core_plugins/timelion/server/series_functions/es/index.js @@ -127,7 +127,7 @@ export default new Datasource('es', { }); } - const esShardTimeout = await tlConfig.server.newPlatform.start.core.elasticsearch.legacy.config$.pipe( + const esShardTimeout = await tlConfig.server.newPlatform.setup.core.elasticsearch.legacy.config$.pipe( first(), map(config => config.shardTimeout.asMilliseconds()) ).toPromise(); diff --git a/src/legacy/server/kbn_server.js b/src/legacy/server/kbn_server.js index a0426869d736e..c571785dd51e9 100644 --- a/src/legacy/server/kbn_server.js +++ b/src/legacy/server/kbn_server.js @@ -57,7 +57,7 @@ export default class KbnServer { const { plugins, elasticsearch, serverOptions, handledConfigPaths } = core; this.newPlatform = { - start: { + setup: { core: { elasticsearch, }, diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js index de17e8d09472a..cab15b2017f42 100644 --- a/src/legacy/ui/ui_render/ui_render_mixin.js +++ b/src/legacy/ui/ui_render/ui_render_mixin.js @@ -216,7 +216,7 @@ export function uiRenderMixin(kbnServer, server, config) { // Get the list of new platform plugins. // Convert the Map into an array of objects so it is JSON serializable and order is preserved. const uiPlugins = [ - ...kbnServer.newPlatform.start.plugins.uiPlugins.public.entries() + ...kbnServer.newPlatform.setup.plugins.uiPlugins.public.entries() ].map(([id, plugin]) => ({ id, plugin })); const nonce = await generateCSPNonce(); From 2c48da24178e07650ca98fcfec36bd8d953da29b Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Mon, 25 Mar 2019 09:26:53 -0700 Subject: [PATCH 23/96] [APM] Rename "Tags" -> "Labels" in span flyout (#33688) * [APM] Closes #33486. Rename "Tags" -> "Labels" in span flyout. * Remove unused translation 'xpack.apm.transactionDetails.spanFlyout.tagsTabLabel' --- .../Waterfall/SpanFlyout/index.tsx | 14 +++++++------- .../plugins/translations/translations/zh-CN.json | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/SpanFlyout/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/SpanFlyout/index.tsx index b2ed17d1017a3..c81b4e522068f 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/SpanFlyout/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/SpanFlyout/index.tsx @@ -57,10 +57,10 @@ export function SpanFlyout({ const codeLanguage = idx(parentTransaction, _ => _.service.language.name); const dbContext = idx(span, _ => _.span.db); const httpContext = idx(span, _ => _.span.http); - const labels = span.labels; - const tags = keys(labels).map(key => ({ + const spanLabels = span.labels; + const labels = keys(spanLabels).map(key => ({ key, - value: get(labels, key) + value: get(spanLabels, key) })); return ( @@ -123,11 +123,11 @@ export function SpanFlyout({ ) }, { - id: 'tags', + id: 'labels', name: i18n.translate( - 'xpack.apm.transactionDetails.spanFlyout.tagsTabLabel', + 'xpack.apm.propertiesTable.tabs.labelsLabel', { - defaultMessage: 'Tags' + defaultMessage: 'Labels' } ), content: ( @@ -144,7 +144,7 @@ export function SpanFlyout({ field: 'value' } ]} - items={tags} + items={labels} /> ) diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index a6866aa2dab68..fc13958a38912 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3435,7 +3435,6 @@ "xpack.apm.transactionDetails.spanFlyout.spanDetailsTitle": "跨度详情", "xpack.apm.transactionDetails.spanFlyout.spanType.navigationTimingLabel": "导航定时", "xpack.apm.transactionDetails.spanFlyout.stackTraceTabLabel": "堆栈追溯", - "xpack.apm.transactionDetails.spanFlyout.tagsTabLabel": "标记", "xpack.apm.transactionDetails.spanFlyout.typeLabel": "类型", "xpack.apm.transactionDetails.spanFlyout.viewSpanInDiscoverButtonLabel": "在 Discover 中查看跨度", "xpack.apm.transactionDetails.timestampLabel": "时间戳", From 2e232c2e31cdc9ebcf1c75201571f82be003ea2d Mon Sep 17 00:00:00 2001 From: Spencer Date: Mon, 25 Mar 2019 09:56:48 -0700 Subject: [PATCH 24/96] [@kbn/expect] "fork" expect.js into repo (#33761) * [@kbn/expect] "fork" expect.js into repo * [eslint] autofix references to expect.js * [tslint] autofix all expect.js imports * now that expect.js is in strict mode, avoid reassigning fn.length --- .eslintrc.js | 9 + TYPESCRIPT.md | 2 +- .../development-functional-tests.asciidoc | 6 +- package.json | 2 +- packages/elastic-datemath/test/index.js | 2 +- packages/kbn-dev-utils/package.json | 4 +- packages/kbn-es-query/package.json | 2 +- .../src/es_query/__tests__/_migrate_filter.js | 2 +- .../src/es_query/__tests__/build_es_query.js | 2 +- .../src/es_query/__tests__/decorate_query.js | 2 +- .../__tests__/filter_matches_index.js | 2 +- .../src/es_query/__tests__/from_filters.js | 2 +- .../src/es_query/__tests__/from_kuery.js | 2 +- .../src/es_query/__tests__/from_lucene.js | 2 +- .../__tests__/lucene_string_to_dsl.js | 2 +- .../src/filters/__tests__/phrase.js | 2 +- .../src/filters/__tests__/query.js | 2 +- .../src/filters/__tests__/range.js | 2 +- .../src/kuery/ast/__tests__/ast.js | 2 +- .../filter_migration/__tests__/exists.js | 2 +- .../__tests__/filter_to_kuery.js | 2 +- .../__tests__/geo_bounding_box.js | 2 +- .../filter_migration/__tests__/geo_polygon.js | 2 +- .../filter_migration/__tests__/phrase.js | 2 +- .../kuery/filter_migration/__tests__/range.js | 2 +- .../src/kuery/functions/__tests__/and.js | 2 +- .../src/kuery/functions/__tests__/exists.js | 2 +- .../functions/__tests__/geo_bounding_box.js | 2 +- .../kuery/functions/__tests__/geo_polygon.js | 2 +- .../src/kuery/functions/__tests__/is.js | 2 +- .../src/kuery/functions/__tests__/not.js | 2 +- .../src/kuery/functions/__tests__/or.js | 2 +- .../src/kuery/functions/__tests__/range.js | 2 +- .../functions/__tests__/utils/get_fields.js | 2 +- .../kuery/node_types/__tests__/function.js | 2 +- .../src/kuery/node_types/__tests__/literal.js | 2 +- .../kuery/node_types/__tests__/named_arg.js | 2 +- .../kuery/node_types/__tests__/wildcard.js | 2 +- packages/kbn-eslint-plugin-eslint/index.js | 1 + .../rules/module_migration.js | 82 ++ packages/kbn-expect/LICENSE.txt | 22 + packages/kbn-expect/README.md | 191 ++++ packages/kbn-expect/expect.js | 971 ++++++++++++++++++ packages/kbn-expect/expect.js.d.ts | 221 ++++ packages/kbn-expect/package.json | 7 + packages/kbn-expect/tsconfig.json | 6 + .../template/package_template.json | 4 +- .../template/public/__tests__/index.js | 2 +- .../template/server/__tests__/index.js | 2 +- packages/kbn-test-subj-selector/package.json | 2 +- packages/kbn-test-subj-selector/test/index.js | 2 +- packages/kbn-test/types/README.md | 1 - packages/kbn-test/types/expect.js.d.ts | 225 ---- src/dev/__tests__/file.js | 2 +- src/dev/__tests__/node_versions_must_match.js | 2 +- src/dev/build/lib/__tests__/build.js | 2 +- src/dev/build/lib/__tests__/config.js | 2 +- src/dev/build/lib/__tests__/errors.js | 2 +- src/dev/build/lib/__tests__/fs.js | 2 +- src/dev/build/lib/__tests__/platform.js | 2 +- src/dev/build/lib/__tests__/runner.js | 2 +- src/dev/build/lib/__tests__/version_info.js | 2 +- .../build/tasks/nodejs/__tests__/download.js | 2 +- .../__tests__/download_node_builds_task.js | 2 +- .../tasks/nodejs/__tests__/node_shasums.js | 2 +- .../verify_existing_node_builds_task.js | 2 +- src/dev/license_checker/__tests__/valid.js | 2 +- .../__tests__/junit_report_generation.js | 2 +- src/dev/npm/__tests__/installed_packages.js | 2 +- src/dev/tslint/rules/moduleMigrationRule.js | 59 ++ src/es_archiver/lib/__tests__/stats.js | 2 +- .../lib/archives/__tests__/format.js | 2 +- .../lib/archives/__tests__/parse.js | 2 +- .../__tests__/generate_doc_records_stream.js | 2 +- .../__tests__/index_doc_records_stream.js | 2 +- .../indices/__tests__/create_index_stream.js | 2 +- .../generate_index_records_stream.js | 2 +- .../__tests__/filter_records_stream.js | 2 +- .../fixtures/simple_project/tests.js | 2 +- .../__tests__/integration/basic.js | 2 +- .../__tests__/integration/failure_hooks.js | 2 +- .../lib/config/__tests__/read_config_file.js | 2 +- .../core_plugins/console/__tests__/index.js | 2 +- .../console/public/src/__tests__/utils.js | 2 +- .../__tests__/elasticsearch_proxy_config.js | 2 +- .../console/server/__tests__/proxy_config.js | 2 +- .../__tests__/proxy_config_collection.js | 2 +- .../server/__tests__/proxy_route/body.js | 2 +- .../server/__tests__/proxy_route/headers.js | 2 +- .../server/__tests__/proxy_route/params.js | 2 +- .../__tests__/proxy_route/query_string.js | 2 +- .../console/server/__tests__/set_headers.js | 2 +- .../lib/__tests__/ensure_es_version.js | 2 +- .../lib/__tests__/health_check.js | 2 +- .../__tests__/is_es_compatible_with_kibana.js | 2 +- .../public/control/control.test.js | 2 +- .../filter_manager/filter_manager.test.js | 2 +- .../phrase_filter_manager.test.js | 2 +- .../range_filter_manager.test.js | 2 +- .../public/lineage/lineage_map.test.js | 2 +- .../public/lineage/parent_candidates.test.js | 2 +- .../server/lib/__tests__/create_handlers.js | 2 +- .../public/__tests__/doc_views.js | 2 +- .../public/editors/__tests__/point_series.js | 2 +- .../field_formats/types/__tests__/boolean.js | 2 +- .../field_formats/types/__tests__/bytes.js | 2 +- .../field_formats/types/__tests__/color.js | 2 +- .../field_formats/types/__tests__/date.js | 2 +- .../field_formats/types/__tests__/duration.js | 2 +- .../field_formats/types/__tests__/ip.js | 2 +- .../field_formats/types/__tests__/number.js | 2 +- .../field_formats/types/__tests__/percent.js | 2 +- .../types/__tests__/relative_date.js | 2 +- .../field_formats/types/__tests__/string.js | 2 +- .../field_formats/types/__tests__/truncate.js | 2 +- .../field_formats/types/__tests__/url.js | 2 +- .../highlight/__tests__/highlight_html.js | 2 +- .../highlight/__tests__/highlight_request.js | 2 +- .../convert_pattern_and_ingest_name.js | 2 +- .../utils/__tests__/as_pretty_string.js | 2 +- .../utils/__tests__/shorten_dotted_string.js | 2 +- .../public/context/api/__tests__/anchor.js | 2 +- .../context/api/__tests__/predecessors.js | 2 +- .../context/api/__tests__/successors.js | 2 +- .../context/api/utils/__tests__/sorting.js | 2 +- .../__tests__/action_add_filter.js | 2 +- .../action_increase_predecessor_count.js | 2 +- .../action_increase_successor_count.js | 2 +- .../__tests__/action_set_predecessor_count.js | 2 +- .../__tests__/action_set_query_parameters.js | 2 +- .../__tests__/action_set_successor_count.js | 2 +- .../dashboard/__tests__/saved_dashboards.js | 2 +- .../dashboard/panel/__tests__/panel_state.ts | 2 +- .../hacks/__tests__/hide_empty_tools.js | 2 +- .../__tests__/directives/discover_field.js | 2 +- .../__tests__/directives/field_calculator.js | 2 +- .../__tests__/directives/field_chooser.js | 2 +- .../public/discover/__tests__/hit_sort_fn.js | 2 +- .../kibana/public/doc/__tests__/doc.js | 2 +- .../field_formats/__tests__/_boolean.js | 2 +- .../public/field_formats/__tests__/_color.js | 2 +- .../field_formats/__tests__/_conformance.js | 2 +- .../public/field_formats/__tests__/_date.js | 2 +- .../field_formats/__tests__/_duration.js | 2 +- .../public/field_formats/__tests__/_ip.js | 2 +- .../public/field_formats/__tests__/_source.js | 2 +- .../public/field_formats/__tests__/_string.js | 2 +- .../field_formats/__tests__/_truncate.js | 2 +- .../public/field_formats/__tests__/_url.js | 2 +- .../lib/__tests__/default_category.test.js | 2 +- .../lib/__tests__/get_aria_name.test.js | 2 +- .../lib/__tests__/get_category_name.test.js | 2 +- .../lib/__tests__/get_val_type.test.js | 2 +- .../lib/__tests__/is_default_value.test.js | 2 +- .../lib/__tests__/to_editable_config.test.js | 2 +- .../server/lib/__tests__/handle_es_error.js | 2 +- .../server/lib/__tests__/manage_uuid.js | 2 +- .../server/lib/__tests__/relationships.js | 2 +- .../kibana/server/lib/__tests__/system_api.js | 2 +- .../saved_objects/get_saved_objects.test.js | 2 +- .../metric_vis/public/__tests__/metric_vis.js | 2 +- .../public/__tests__/metric_vis_controller.js | 2 +- .../__tests__/region_map_visualization.js | 2 +- .../public/__tests__/_table_vis_controller.js | 2 +- .../tagcloud/public/__tests__/tag_cloud.js | 2 +- .../__tests__/tag_cloud_visualization.js | 2 +- .../coordinate_maps_visualization.js | 2 +- .../public/__tests__/geohash_layer.js | 2 +- .../public/__tests__/_tick_generator.js | 2 +- .../__tests__/services/tick_formatters.js | 2 +- .../timelion_expression_input_helpers.js | 2 +- .../timelion_expression_suggestions.js | 2 +- .../timelion/server/lib/offset_time.test.js | 2 +- .../public/__tests__/vega_visualization.js | 2 +- .../data_model/__tests__/es_query_parser.js | 2 +- .../data_model/__tests__/search_cache.js | 2 +- .../public/data_model/__tests__/time_cache.js | 2 +- .../data_model/__tests__/vega_parser.js | 2 +- .../deprecation/__tests__/create_transform.js | 2 +- .../deprecations/__tests__/rename.js | 2 +- .../deprecations/__tests__/unused.js | 2 +- .../__tests__/find_plugin_specs.js | 2 +- .../__tests__/extend_config_service.js | 2 +- .../plugin_config/__tests__/schema.js | 2 +- .../plugin_config/__tests__/settings.js | 2 +- .../__tests__/reduce_export_specs.js | 2 +- .../plugin_pack/__tests__/create_pack.js | 2 +- .../__tests__/package_json_at_path.js | 2 +- .../__tests__/package_jsons_in_directory.js | 2 +- .../plugin_pack/__tests__/plugin_pack.js | 2 +- .../__tests__/is_version_compatible.js | 2 +- .../plugin_spec/__tests__/plugin_spec.js | 2 +- .../config/__tests__/deprecation_warnings.js | 2 +- .../usage/classes/__tests__/collector_set.js | 2 +- .../ui_exports_replace_injected_vars.js | 2 +- .../field_formats/__tests__/field_format.js | 2 +- .../__tests__/field_formats_mixin.js | 2 +- .../__tests__/field_formats_service.js | 2 +- src/legacy/ui/public/__tests__/errors.js | 2 +- src/legacy/ui/public/__tests__/metadata.js | 2 +- .../__tests__/kbn_accessible_click.js | 2 +- .../__tests__/kbn_ui_ace_keyboard_mode.js | 2 +- .../__tests__/scrollto_activedescendant.js | 2 +- .../hierarchical/__tests__/collect_branch.js | 2 +- .../point_series/__tests__/_add_to_siri.js | 2 +- .../point_series/__tests__/_fake_x_aspect.js | 2 +- .../point_series/__tests__/_get_aspects.js | 2 +- .../point_series/__tests__/_get_point.js | 2 +- .../point_series/__tests__/_get_series.js | 2 +- .../point_series/__tests__/_init_x_axis.js | 2 +- .../point_series/__tests__/_init_y_axis.js | 2 +- .../point_series/__tests__/_main.js | 2 +- .../__tests__/_ordered_date_axis.js | 2 +- .../__tests__/_tooltip_formatter.js | 2 +- .../agg_response/tabify/__tests__/_buckets.js | 2 +- .../tabify/__tests__/_get_columns.js | 2 +- .../tabify/__tests__/_integration.js | 2 +- .../tabify/__tests__/_response_writer.js | 2 +- .../ui/public/agg_table/__tests__/_group.js | 2 +- .../ui/public/agg_table/__tests__/_table.js | 2 +- .../public/agg_types/__tests__/agg_params.js | 2 +- .../ui/public/agg_types/__tests__/agg_type.js | 2 +- .../agg_types/__tests__/buckets/_geo_hash.js | 2 +- .../agg_types/__tests__/buckets/_histogram.js | 2 +- .../agg_types/__tests__/buckets/_range.js | 2 +- .../buckets/_terms_other_bucket_helper.js | 2 +- .../buckets/create_filter/date_histogram.js | 2 +- .../buckets/create_filter/date_range.js | 2 +- .../buckets/create_filter/filters.js | 2 +- .../buckets/create_filter/histogram.js | 2 +- .../buckets/create_filter/ip_range.js | 2 +- .../__tests__/buckets/create_filter/range.js | 2 +- .../__tests__/buckets/create_filter/terms.js | 2 +- .../buckets/date_histogram/_editor.js | 2 +- .../buckets/date_histogram/_params.js | 2 +- .../agg_types/__tests__/buckets/terms.js | 2 +- .../__tests__/controls/number_list.js | 2 +- .../directives/auto_select_if_only_one.js | 2 +- .../__tests__/directives/input_number.js | 2 +- .../directives/validate_cidr_mask.js | 2 +- .../directives/validate_date_math.js | 2 +- .../__tests__/directives/validate_ip.js | 2 +- .../ui/public/agg_types/__tests__/index.js | 2 +- .../metrics/lib/make_nested_label.js | 2 +- .../agg_types/__tests__/metrics/median.js | 2 +- .../__tests__/metrics/parent_pipeline.js | 2 +- .../__tests__/metrics/percentile_ranks.js | 2 +- .../__tests__/metrics/percentiles.js | 2 +- .../__tests__/metrics/sibling_pipeline.js | 2 +- .../__tests__/metrics/std_deviation.js | 2 +- .../agg_types/__tests__/metrics/top_hit.js | 2 +- .../agg_types/__tests__/param_types/_field.js | 2 +- .../agg_types/__tests__/param_types/_json.js | 2 +- .../__tests__/param_types/_optioned.js | 2 +- .../agg_types/__tests__/param_types/_regex.js | 2 +- .../__tests__/param_types/_string.js | 2 +- src/legacy/ui/public/bind/__tests__/bind.js | 2 +- .../ui/public/binder/__tests__/binder.js | 2 +- .../public/chrome/__tests__/nav_controls.js | 2 +- .../ui/public/chrome/api/__tests__/apps.js | 2 +- .../ui/public/chrome/api/__tests__/nav.js | 2 +- .../ui/public/chrome/api/__tests__/xsrf.js | 2 +- .../__tests__/sub_url_route_filter.js | 2 +- .../ui/public/config/__tests__/config.js | 2 +- .../courier/fetch/__tests__/call_client.js | 2 +- .../courier/fetch/__tests__/fetch_now.js | 2 +- .../__tests__/search_request.js | 2 +- .../segmented_search_request.create_queue.js | 2 +- ...egmented_search_request.index_selection.js | 2 +- .../__tests__/segmented_search_request.js | 2 +- .../segmented_search_request.size_picking.js | 2 +- .../__tests__/serialize_fetch_params.js | 2 +- .../__tests__/search_request_queue.js | 2 +- .../__tests__/normalize_sort_request.js | 2 +- .../search_source/__tests__/search_source.js | 2 +- .../ui/public/debounce/__tests__/debounce.js | 2 +- .../directives/__tests__/css_truncate.js | 2 +- .../directives/__tests__/fixed_scroll.js | 2 +- .../public/directives/__tests__/inequality.js | 2 +- .../directives/__tests__/input_focus.js | 2 +- .../public/directives/__tests__/json_input.js | 2 +- .../__tests__/paginated_selectable_list.js | 2 +- .../directives/__tests__/parse_query.js | 2 +- .../public/directives/__tests__/truncate.js | 2 +- .../directives/__tests__/validate_json.js | 2 +- .../doc_table/__tests__/actions/filter.js | 2 +- .../public/doc_table/__tests__/doc_table.js | 2 +- .../doc_table/__tests__/lib/get_sort.js | 2 +- .../doc_table/__tests__/lib/rows_headers.js | 2 +- .../public/doc_title/__tests__/doc_title.js | 2 +- .../public/doc_viewer/__tests__/doc_viewer.js | 2 +- .../__tests__/documentation_links.js | 2 +- .../public/draggable/__tests__/draggable.js | 2 +- .../error_url_overflow/__tests__/ie_regex.js | 2 +- .../public/factories/__tests__/base_object.js | 2 +- .../ui/public/factories/__tests__/events.js | 2 +- .../fancy_forms/__tests__/fancy_forms.js | 2 +- .../__tests__/nested_fancy_forms.js | 2 +- .../__tests__/field_wildcard.js | 2 +- .../filter_bar/__tests__/_add_filters.js | 2 +- .../filter_bar/__tests__/_get_filters.js | 2 +- .../filter_bar/__tests__/_invert_filters.js | 2 +- .../filter_bar/__tests__/_pin_filters.js | 2 +- .../filter_bar/__tests__/_remove_filters.js | 2 +- .../filter_bar/__tests__/_toggle_filters.js | 2 +- .../filter_bar/__tests__/push_filter.js | 2 +- .../filter_bar/__tests__/query_filter.js | 2 +- .../lib/__tests__/change_time_filter.test.js | 2 +- .../filter_bar/lib/__tests__/dedup_filters.js | 2 +- .../lib/__tests__/extract_time_filter.js | 2 +- .../lib/__tests__/generate_mapping_chain.js | 2 +- .../lib/__tests__/map_and_flatten_filters.js | 2 +- .../filter_bar/lib/__tests__/map_default.js | 2 +- .../filter_bar/lib/__tests__/map_exists.js | 2 +- .../filter_bar/lib/__tests__/map_filter.js | 2 +- .../__tests__/map_flatten_and_wrap_filters.js | 2 +- .../lib/__tests__/map_geo_bounding_box.js | 2 +- .../lib/__tests__/map_geo_polygon.js | 2 +- .../filter_bar/lib/__tests__/map_match_all.js | 2 +- .../filter_bar/lib/__tests__/map_missing.js | 2 +- .../filter_bar/lib/__tests__/map_phrase.js | 2 +- .../lib/__tests__/map_query_string.js | 2 +- .../filter_bar/lib/__tests__/map_range.js | 2 +- .../filter_bar/lib/__tests__/only_disabled.js | 2 +- .../filter_bar/lib/__tests__/uniq_filters.js | 2 +- .../__tests__/filter_manager.js | 2 +- .../ui/public/filters/__tests__/comma_list.js | 2 +- .../ui/public/filters/__tests__/field_type.js | 2 +- .../ui/public/filters/__tests__/label.js | 2 +- .../ui/public/filters/__tests__/moment.js | 2 +- .../public/filters/__tests__/prop_filter.js | 2 +- .../ui/public/filters/__tests__/rison.js | 2 +- .../ui/public/filters/__tests__/short_dots.js | 2 +- .../ui/public/filters/__tests__/start_from.js | 2 +- .../ui/public/filters/__tests__/uriescape.js | 2 +- .../__tests__/_get_computed_fields.js | 2 +- .../__tests__/_index_pattern.js | 2 +- .../index_patterns/__tests__/flatten_hit.js | 2 +- .../__tests__/index_patterns.js | 2 +- .../index_patterns/__tests__/intervals.js | 2 +- .../__tests__/unsupported_time_patterns.js | 2 +- .../static_utils/__tests__/index.js | 2 +- .../indexed_array/__tests__/indexed_array.js | 2 +- .../indexed_array/__tests__/inflector.js | 2 +- .../jquery/__tests__/find_test_subject.js | 2 +- .../kbn_top_nav/__tests__/kbn_top_nav.js | 2 +- .../__tests__/kbn_top_nav_controller.js | 2 +- .../ui/public/listen/__tests__/listen.js | 2 +- .../ui/public/management/__tests__/index.js | 2 +- .../ui/public/management/__tests__/section.js | 2 +- .../public/modals/__tests__/confirm_modal.js | 2 +- .../modals/__tests__/confirm_modal_promise.js | 2 +- .../ui/public/notify/__tests__/notifier.js | 2 +- .../public/notify/lib/format_es_msg.test.js | 2 +- .../ui/public/notify/lib/format_msg.test.js | 2 +- .../public/paginated_table/__tests__/index.js | 2 +- .../__tests__/persisted_state_provider.js | 2 +- .../ui/public/private/__tests__/private.js | 2 +- .../ui/public/promises/__tests__/promises.js | 2 +- .../ui/public/registry/__tests__/registry.js | 2 +- .../__tests__/render_directive.js | 2 +- .../__tests__/resize_checker.js | 2 +- .../public/routes/__tests__/_route_manager.js | 2 +- .../ui/public/routes/__tests__/_work_queue.js | 2 +- .../routes/__tests__/_wrap_route_with_prep.js | 2 +- .../__tests__/find_object_by_title.js | 2 +- .../saved_objects/__tests__/saved_object.js | 2 +- .../__tests__/simple_saved_object.js | 2 +- .../ui/public/share/lib/url_shortener.test.js | 2 +- .../state_management/__tests__/app_state.js | 2 +- .../__tests__/config_provider.js | 2 +- .../__tests__/global_state.js | 2 +- .../state_management/__tests__/state.js | 2 +- .../__tests__/state_monitor_factory.js | 2 +- .../state_hashing/__tests__/hash_url.js | 2 +- .../state_hashing/__tests__/unhash_url.js | 2 +- .../__tests__/hashed_item_store.js | 2 +- .../state_storage/__tests__/state_hash.js | 2 +- .../ui/public/storage/__tests__/storage.js | 2 +- .../style_compile/__tests__/style_compile.js | 2 +- .../public/system_api/__tests__/system_api.js | 2 +- .../ui/public/timefilter/get_time.test.ts | 2 +- .../lib/diff_time_picker_vals.test.js | 2 +- .../ui/public/timefilter/timefilter.test.js | 2 +- .../url/__tests__/extract_app_path_and_id.js | 2 +- .../public/url/__tests__/kibana_parsed_url.js | 2 +- .../ui/public/url/__tests__/prepend_path.js | 2 +- src/legacy/ui/public/url/__tests__/url.js | 2 +- .../utils/__tests__/brush_event.test.js | 2 +- .../ui/public/utils/__tests__/cidr_mask.ts | 2 +- .../ui/public/utils/__tests__/collection.js | 2 +- .../public/utils/__tests__/decode_geo_hash.js | 2 +- .../ui/public/utils/__tests__/diff_object.js | 2 +- .../ui/public/utils/__tests__/ipv4_address.ts | 2 +- .../public/utils/__tests__/mapping_setup.js | 2 +- .../ui/public/utils/__tests__/obj_define.js | 2 +- .../public/utils/__tests__/ordinal_suffix.js | 2 +- .../public/utils/__tests__/parse_interval.js | 2 +- src/legacy/ui/public/utils/__tests__/range.js | 2 +- .../public/utils/__tests__/simple_emitter.js | 2 +- .../utils/__tests__/sort_prefix_first.js | 2 +- .../ui/public/vis/__tests__/_agg_config.js | 2 +- .../vis/__tests__/_agg_config_result.js | 2 +- .../ui/public/vis/__tests__/_agg_configs.js | 2 +- src/legacy/ui/public/vis/__tests__/_vis.js | 2 +- .../public/vis/__tests__/components/color.js | 2 +- .../ui/public/vis/__tests__/map/ems_client.js | 2 +- .../ui/public/vis/__tests__/map/kibana_map.js | 2 +- .../vis/__tests__/map/service_settings.js | 2 +- .../response_handlers/_build_chart_data.js | 2 +- .../vis/__tests__/response_handlers/basic.js | 2 +- .../vis/__tests__/vis_types/base_vis_type.js | 2 +- .../vis/__tests__/vis_types/react_vis_type.js | 2 +- .../__tests__/vis_types/vislib_vis_type.js | 2 +- .../tooltip/__tests__/positioning.js | 2 +- .../vis/editors/default/__tests__/agg.js | 2 +- .../editors/default/__tests__/agg_params.js | 2 +- .../default/__tests__/keyboard_move.js | 2 +- .../vis_types/__tests__/vislib_vis_legend.js | 2 +- .../__tests__/components/heatmap_color.js | 2 +- .../vislib/__tests__/components/labels.js | 2 +- .../__tests__/components/zero_injection.js | 2 +- .../ui/public/vislib/__tests__/index.js | 2 +- .../public/vislib/__tests__/lib/axis/axis.js | 2 +- .../public/vislib/__tests__/lib/axis_title.js | 2 +- .../vislib/__tests__/lib/chart_title.js | 2 +- .../ui/public/vislib/__tests__/lib/data.js | 2 +- .../public/vislib/__tests__/lib/dispatch.js | 2 +- .../vislib/__tests__/lib/error_handler.js | 2 +- .../vislib/__tests__/lib/handler/handler.js | 2 +- .../vislib/__tests__/lib/layout/layout.js | 2 +- .../__tests__/lib/layout/layout_types.js | 2 +- .../lib/layout/splits/column_chart/splits.js | 2 +- .../lib/layout/splits/gauge_chart/splits.js | 2 +- .../lib/layout/types/column_layout.js | 2 +- .../__tests__/lib/types/point_series.js | 2 +- .../public/vislib/__tests__/lib/vis_config.js | 2 +- .../ui/public/vislib/__tests__/lib/x_axis.js | 2 +- .../ui/public/vislib/__tests__/lib/y_axis.js | 2 +- src/legacy/ui/public/vislib/__tests__/vis.js | 2 +- .../__tests__/visualizations/area_chart.js | 2 +- .../vislib/__tests__/visualizations/chart.js | 2 +- .../__tests__/visualizations/column_chart.js | 2 +- .../__tests__/visualizations/gauge_chart.js | 2 +- .../__tests__/visualizations/heatmap_chart.js | 2 +- .../__tests__/visualizations/line_chart.js | 2 +- .../__tests__/visualizations/pie_chart.js | 2 +- .../__tests__/visualizations/time_marker.js | 2 +- .../__tests__/visualizations/vis_types.js | 2 +- .../loader/__tests__/visualization_loader.js | 2 +- .../loader/__tests__/visualize_data_loader.js | 2 +- .../loader/__tests__/visualize_loader.js | 2 +- .../watch_multi/__tests__/watch_multi.js | 2 +- src/legacy/ui/ui_apps/__tests__/ui_app.js | 2 +- .../__tests__/app_entry_template.js | 2 +- .../ui/ui_bundles/__tests__/ui_bundle.js | 2 +- .../__tests__/collect_ui_exports.js | 2 +- .../ui/ui_nav_links/__tests__/ui_nav_link.js | 2 +- .../lib/create_objects_client_stub.js | 2 +- .../ui_settings_mixin_integration.js | 2 +- .../__tests__/ui_settings_service.js | 2 +- .../create_or_upgrade_integration.js | 2 +- .../create_or_upgrade_saved_config.js | 2 +- .../is_config_version_upgradeable.js | 2 +- .../routes/__tests__/doc_exists.js | 2 +- .../routes/__tests__/doc_missing.js | 2 +- .../doc_missing_and_index_read_only.js | 2 +- src/legacy/utils/__tests__/kbn_field_types.js | 2 +- src/legacy/utils/__tests__/unset.js | 2 +- .../strings/__tests__/comma_separated_list.js | 2 +- src/legacy/utils/strings/__tests__/prose.js | 2 +- .../bundles_route/__tests__/bundles_route.js | 2 +- src/test_utils/__tests__/get_url.js | 2 +- src/test_utils/expect_deep_equal.js | 2 +- test/api_integration/apis/general/cookies.js | 2 +- test/api_integration/apis/general/csp.js | 2 +- test/api_integration/apis/home/sample_data.js | 2 +- .../apis/index_patterns/es_errors/errors.js | 2 +- .../es_errors/lib/get_es_errors.js | 2 +- .../fields_for_time_pattern_route/pattern.js | 2 +- .../query_params.js | 2 +- .../fields_for_wildcard_route/conflicts.js | 2 +- .../fields_for_wildcard_route/response.js | 2 +- .../apis/kql_telemetry/kql_telemetry.js | 2 +- .../management/saved_objects/relationships.js | 2 +- .../apis/saved_objects/bulk_create.js | 2 +- .../apis/saved_objects/bulk_get.js | 2 +- .../apis/saved_objects/create.js | 2 +- .../apis/saved_objects/delete.js | 2 +- .../apis/saved_objects/export.js | 2 +- .../apis/saved_objects/find.js | 2 +- .../api_integration/apis/saved_objects/get.js | 2 +- .../apis/saved_objects/import.js | 2 +- .../saved_objects/resolve_import_errors.js | 2 +- .../apis/saved_objects/update.js | 2 +- .../api_integration/apis/scripts/languages.js | 2 +- test/api_integration/apis/search/count.js | 2 +- test/api_integration/apis/shorten/index.js | 2 +- test/api_integration/apis/stats/stats.js | 2 +- test/api_integration/apis/status/status.js | 2 +- .../apis/user_action/user_action.js | 2 +- test/functional/apps/console/_console.ts | 2 +- .../apps/context/_discover_navigation.js | 2 +- test/functional/apps/context/_filters.js | 2 +- test/functional/apps/context/_size.js | 2 +- .../apps/dashboard/bwc_shared_urls.js | 2 +- .../dashboard/create_and_add_embeddables.js | 2 +- .../apps/dashboard/dashboard_clone.js | 2 +- .../apps/dashboard/dashboard_filter_bar.js | 2 +- .../apps/dashboard/dashboard_filtering.js | 2 +- .../apps/dashboard/dashboard_grid.js | 2 +- .../apps/dashboard/dashboard_listing.js | 2 +- .../apps/dashboard/dashboard_options.js | 2 +- .../apps/dashboard/dashboard_query_bar.js | 2 +- .../apps/dashboard/dashboard_save.js | 2 +- .../apps/dashboard/dashboard_snapshots.js | 2 +- .../apps/dashboard/dashboard_state.js | 2 +- .../apps/dashboard/dashboard_time.js | 2 +- .../apps/dashboard/data_shared_attributes.js | 2 +- test/functional/apps/dashboard/embed_mode.js | 2 +- .../apps/dashboard/embeddable_rendering.js | 2 +- .../apps/dashboard/empty_dashboard.js | 2 +- .../apps/dashboard/full_screen_mode.js | 2 +- .../apps/dashboard/panel_controls.js | 2 +- .../apps/dashboard/panel_expand_toggle.js | 2 +- test/functional/apps/dashboard/time_zones.js | 2 +- test/functional/apps/dashboard/view_edit.js | 2 +- test/functional/apps/discover/_discover.js | 2 +- test/functional/apps/discover/_errors.js | 2 +- test/functional/apps/discover/_field_data.js | 2 +- test/functional/apps/discover/_inspector.js | 2 +- .../functional/apps/discover/_large_string.js | 2 +- .../functional/apps/discover/_shared_links.js | 2 +- test/functional/apps/discover/_sidebar.js | 2 +- .../apps/discover/_source_filters.js | 2 +- .../apps/getting_started/_shakespeare.js | 2 +- test/functional/apps/home/_add_data.js | 2 +- test/functional/apps/home/_home.js | 2 +- test/functional/apps/home/_navigation.js | 2 +- test/functional/apps/home/_sample_data.js | 2 +- .../_create_index_pattern_wizard.js | 2 +- .../apps/management/_handle_alias.js | 2 +- .../management/_handle_version_conflict.js | 2 +- .../apps/management/_import_objects.js | 2 +- .../_index_pattern_create_delete.js | 2 +- .../apps/management/_index_pattern_filter.js | 2 +- .../management/_index_pattern_popularity.js | 2 +- .../management/_index_pattern_results_sort.js | 2 +- .../apps/management/_kibana_settings.js | 2 +- .../management/_mgmt_import_saved_objects.js | 2 +- .../apps/management/_scripted_fields.js | 2 +- .../management/_scripted_fields_filter.js | 2 +- .../management/_scripted_fields_preview.js | 2 +- .../apps/management/_test_huge_fields.js | 2 +- test/functional/apps/status_page/index.js | 2 +- .../apps/timelion/_expression_typeahead.js | 2 +- test/functional/apps/visualize/_area_chart.js | 2 +- .../functional/apps/visualize/_chart_types.js | 2 +- test/functional/apps/visualize/_data_table.js | 2 +- .../visualize/_data_table_nontimeindex.js | 2 +- .../apps/visualize/_embedding_chart.js | 2 +- .../apps/visualize/_experimental_vis.js | 2 +- .../functional/apps/visualize/_gauge_chart.js | 2 +- .../apps/visualize/_heatmap_chart.js | 2 +- .../visualize/_histogram_request_start.js | 2 +- .../apps/visualize/_input_control_vis.js | 2 +- test/functional/apps/visualize/_lab_mode.js | 2 +- test/functional/apps/visualize/_line_chart.js | 2 +- .../apps/visualize/_linked_saved_searches.js | 2 +- .../apps/visualize/_markdown_vis.js | 2 +- .../apps/visualize/_metric_chart.js | 2 +- test/functional/apps/visualize/_pie_chart.js | 2 +- .../apps/visualize/_point_series_options.js | 2 +- test/functional/apps/visualize/_region_map.js | 2 +- .../functional/apps/visualize/_shared_item.js | 2 +- test/functional/apps/visualize/_tag_cloud.js | 2 +- test/functional/apps/visualize/_tile_map.js | 2 +- test/functional/apps/visualize/_tsvb_chart.ts | 2 +- .../apps/visualize/_tsvb_markdown.ts | 2 +- test/functional/apps/visualize/_vega_chart.js | 2 +- .../apps/visualize/_vertical_bar_chart.js | 2 +- .../_vertical_bar_chart_nontimeindex.js | 2 +- .../apps/visualize/_visualize_listing.js | 2 +- test/functional/page_objects/common_page.js | 2 +- test/functional/page_objects/discover_page.js | 2 +- test/functional/page_objects/settings_page.js | 2 +- .../functional/page_objects/visualize_page.js | 2 +- .../services/dashboard/expectations.js | 2 +- test/functional/services/inspector.js | 2 +- .../__tests__/remote_default_window_size.js | 2 +- test/functional/services/snapshots.js | 2 +- .../services/visualizations/pie_chart.js | 2 +- .../test_suites/run_pipeline/basic.js | 2 +- .../test_suites/run_pipeline/helpers.js | 2 +- .../test_suites/app_plugins/app_navigation.js | 2 +- .../self_changing_vis.js | 2 +- .../embedding_visualizations/embed_by_id.js | 2 +- .../panel_actions/panel_actions.js | 2 +- test/tsconfig.json | 3 +- tsconfig.json | 3 +- tslint.yaml | 4 + x-pack/common/__tests__/poller.js | 2 +- x-pack/package.json | 2 +- .../functions/browser/__tests__/markdown.js | 2 +- .../functions/common/__tests__/all.js | 2 +- .../functions/common/__tests__/alterColumn.js | 2 +- .../functions/common/__tests__/any.js | 2 +- .../functions/common/__tests__/as.js | 2 +- .../functions/common/__tests__/axis_config.js | 2 +- .../functions/common/__tests__/case.js | 2 +- .../functions/common/__tests__/clear.js | 2 +- .../functions/common/__tests__/columns.js | 2 +- .../functions/common/__tests__/compare.js | 2 +- .../common/__tests__/container_style.js | 2 +- .../functions/common/__tests__/context.js | 2 +- .../functions/common/__tests__/csv.js | 2 +- .../functions/common/__tests__/date.js | 2 +- .../functions/common/__tests__/do.js | 2 +- .../common/__tests__/dropdown_control.js | 2 +- .../functions/common/__tests__/eq.js | 2 +- .../functions/common/__tests__/exactly.js | 2 +- .../functions/common/__tests__/filterrows.js | 2 +- .../functions/common/__tests__/font.js | 2 +- .../functions/common/__tests__/formatdate.js | 2 +- .../common/__tests__/formatnumber.js | 2 +- .../functions/common/__tests__/getCell.js | 2 +- .../common/__tests__/get_flot_axis_config.js | 2 +- .../common/__tests__/get_font_spec.js | 2 +- .../common/__tests__/get_tick_hash.js | 2 +- .../functions/common/__tests__/gt.js | 2 +- .../functions/common/__tests__/gte.js | 2 +- .../functions/common/__tests__/head.js | 2 +- .../functions/common/__tests__/if.js | 2 +- .../functions/common/__tests__/image.js | 2 +- .../functions/common/__tests__/lt.js | 2 +- .../functions/common/__tests__/lte.js | 2 +- .../functions/common/__tests__/mapColumn.js | 2 +- .../functions/common/__tests__/math.js | 2 +- .../functions/common/__tests__/metric.js | 2 +- .../functions/common/__tests__/neq.js | 2 +- .../functions/common/__tests__/palette.js | 2 +- .../functions/common/__tests__/pie.js | 2 +- .../functions/common/__tests__/plot.js | 2 +- .../functions/common/__tests__/ply.js | 2 +- .../functions/common/__tests__/progress.js | 2 +- .../functions/common/__tests__/render.js | 2 +- .../common/__tests__/repeat_image.js | 2 +- .../functions/common/__tests__/replace.js | 2 +- .../common/__tests__/reveal_image.js | 2 +- .../functions/common/__tests__/rounddate.js | 2 +- .../functions/common/__tests__/rowCount.js | 2 +- .../common/__tests__/series_style.js | 2 +- .../common/__tests__/series_style_to_flot.js | 2 +- .../functions/common/__tests__/sort.js | 2 +- .../common/__tests__/staticColumn.js | 2 +- .../functions/common/__tests__/string.js | 2 +- .../functions/common/__tests__/switch.js | 2 +- .../functions/common/__tests__/table.js | 2 +- .../functions/common/__tests__/tail.js | 2 +- .../functions/common/__tests__/timefilter.js | 2 +- .../common/__tests__/timefilter_control.js | 2 +- .../functions/server/__tests__/demodata.js | 2 +- .../server/__tests__/get_expression_type.js | 2 +- .../server/__tests__/get_field_names.js | 2 +- .../server/__tests__/is_column_reference.js | 2 +- .../functions/server/__tests__/pointseries.js | 2 +- .../datacolumn/__tests__/get_form_object.js | 2 +- .../common/lib/__tests__/autocomplete.js | 2 +- .../common/lib/__tests__/find_in_object.js | 2 +- .../lib/__tests__/get_colors_from_palette.js | 2 +- .../common/lib/__tests__/get_field_type.js | 2 +- .../common/lib/__tests__/get_legend_config.js | 2 +- .../canvas/common/lib/__tests__/httpurl.js | 2 +- .../common/lib/__tests__/latest_change.js | 2 +- .../lib/__tests__/pivot_object_array.js | 2 +- .../common/lib/__tests__/unquote_string.js | 2 +- .../components/download/__tests__/download.js | 2 +- .../components/loading/__tests__/loading.js | 2 +- .../public/functions/__tests__/asset.js | 2 +- .../canvas/public/lib/__tests__/clipboard.js | 2 +- .../public/lib/__tests__/history_provider.js | 2 +- .../public/lib/__tests__/modify_path.js | 2 +- .../public/lib/__tests__/resolved_arg.js | 2 +- .../__tests__/elements.get_sibling_context.js | 2 +- .../state/reducers/__tests__/elements.js | 2 +- .../state/reducers/__tests__/resolved_args.js | 2 +- .../selectors/__tests__/resolved_args.js | 2 +- .../state/selectors/__tests__/workpad.js | 2 +- .../__tests__/collector.handle_response.js | 2 +- .../__tests__/wrap_custom_error.js | 2 +- .../error_wrappers/__tests__/wrap_es_error.js | 2 +- .../__tests__/wrap_unknown_error.js | 2 +- .../__tests__/is_es_error_factory.js | 2 +- .../__tests__/license_pre_routing_factory.js | 2 +- .../__tests__/dashboard_mode_auth_scope.js | 2 +- .../dashboard_mode_request_interceptor.js | 2 +- .../graph/public/__tests__/workspace.js | 2 +- .../server/lib/__tests__/check_license.js | 2 +- .../check_license/__tests__/check_license.js | 2 +- .../__tests__/license_pre_routing_factory.js | 2 +- .../__tests__/grokdebugger_request.js | 2 +- .../__tests__/grokdebugger_response.js | 2 +- .../check_license/__tests__/check_license.js | 2 +- .../__tests__/wrap_custom_error.js | 2 +- .../error_wrappers/__tests__/wrap_es_error.js | 2 +- .../__tests__/wrap_unknown_error.js | 2 +- .../__tests__/is_es_error_factory.js | 2 +- .../__tests__/license_pre_routing_factory.js | 2 +- .../__tests__/conjunction.js | 2 +- .../__tests__/escape_kuery.js | 2 +- .../autocomplete_providers/__tests__/field.js | 2 +- .../__tests__/operator.js | 2 +- .../autocomplete_providers/__tests__/value.js | 2 +- .../common/lib/__tests__/get_moment.js | 2 +- .../check_license/__tests__/check_license.js | 2 +- .../__tests__/wrap_custom_error.js | 2 +- .../error_wrappers/__tests__/wrap_es_error.js | 2 +- .../__tests__/wrap_unknown_error.js | 2 +- .../__tests__/fetch_all_from_scroll.js | 2 +- .../__tests__/license_pre_routing_factory.js | 2 +- .../models/cluster/__tests__/cluster.js | 2 +- .../models/pipeline/__tests__/pipeline.js | 2 +- .../__tests__/pipeline_list_item.js | 2 +- .../ml/common/util/__tests__/anomaly_utils.js | 2 +- .../ml/common/util/__tests__/job_utils.js | 2 +- .../common/util/__tests__/parse_interval.js | 2 +- .../ml/common/util/__tests__/string_utils.js | 2 +- .../__tests__/annotations_table_directive.js | 2 +- .../chart_tooltip/__tests__/chart_tooltip.js | 2 +- .../__tests__/confirm_modal_controller.js | 2 +- .../__tests__/select_interval_directive.js | 2 +- .../form_label/__tests__/form_label.js | 2 +- .../json_tooltip/__tests__/json_tooltip.js | 2 +- .../kql_filter_bar/__tests__/utils.js | 2 +- .../__tests__/loading_indicator_directive.js | 2 +- .../messagebar/__tests__/messagebar.js | 2 +- .../components/rule_editor/__tests__/utils.js | 2 +- .../__tests__/datavisualizer_controller.js | 2 +- .../explorer/__tests__/explorer_controller.js | 2 +- .../__tests__/abbreviate_whole_number.js | 2 +- .../formatters/__tests__/format_value.js | 2 +- .../__tests__/metric_change_description.js | 2 +- .../__tests__/round_to_decimal_place.js | 2 +- .../advanced/__tests__/new_job_controller.js | 2 +- .../detector_filter_modal_controller.js | 2 +- .../__tests__/detector_modal_controller.js | 2 +- .../__tests__/save_status_modal_controller.js | 2 +- .../__tests__/create_job_controller.js | 2 +- .../__tests__/create_job_controller.js | 2 +- .../__tests__/create_job_controller.js | 2 +- .../__tests__/create_job_controller.js | 2 +- .../__tests__/index_or_search_controller.js | 2 +- .../job_type/__tests__/job_type_controller.js | 2 +- .../public/license/__tests__/check_license.js | 2 +- .../__tests__/timeseries_chart_directive.js | 2 +- .../timeseriesexplorer_controller.js | 2 +- .../public/util/__tests__/app_state_utils.js | 2 +- .../ml/public/util/__tests__/chart_utils.js | 2 +- .../public/util/__tests__/custom_url_utils.js | 2 +- .../util/__tests__/field_types_utils.js | 2 +- .../public/util/__tests__/ml_time_buckets.js | 2 +- .../ml/public/util/__tests__/string_utils.js | 2 +- .../client/__tests__/elasticsearch_ml.js | 2 +- .../ml/server/lib/__tests__/query_utils.js | 2 +- .../ml/server/lib/__tests__/security_utils.js | 2 +- .../check_license/__tests__/check_license.js | 2 +- .../__tests__/bucket_span_estimator.js | 2 +- .../__tests__/job_validation.js | 2 +- .../__tests__/validate_bucket_span.js | 2 +- .../__tests__/validate_cardinality.js | 2 +- .../__tests__/validate_influencers.js | 2 +- .../__tests__/validate_model_memory_limit.js | 2 +- .../__tests__/validate_time_range.js | 2 +- .../monitoring/__tests__/deprecations.js | 2 +- .../__tests__/format_timestamp_to_duration.js | 2 +- .../alerts/__tests__/map_severity.js | 2 +- .../components/chart/__tests__/get_color.js | 2 +- .../chart/__tests__/get_last_value.js | 2 +- .../components/chart/__tests__/get_title.js | 2 +- .../chart/__tests__/get_values_for_legend.js | 2 +- .../models/__tests__/config.js | 2 +- .../models/__tests__/pipeline_state.js | 2 +- .../models/graph/__tests__/boolean_edge.js | 2 +- .../models/graph/__tests__/edge.js | 2 +- .../models/graph/__tests__/edge_factory.js | 2 +- .../models/graph/__tests__/if_vertex.js | 2 +- .../models/graph/__tests__/index.js | 2 +- .../models/graph/__tests__/plugin_vertex.js | 2 +- .../models/graph/__tests__/queue_vertex.js | 2 +- .../models/graph/__tests__/vertex.js | 2 +- .../models/graph/__tests__/vertex_factory.js | 2 +- .../models/pipeline/__tests__/if_statement.js | 2 +- .../pipeline/__tests__/make_statement.js | 2 +- .../models/pipeline/__tests__/pipeline.js | 2 +- .../pipeline/__tests__/plugin_statement.js | 2 +- .../models/pipeline/__tests__/queue.js | 2 +- .../models/pipeline/__tests__/statement.js | 2 +- .../models/pipeline/__tests__/utils.js | 2 +- .../__tests__/monitoring_main_controller.js | 2 +- .../public/lib/__tests__/format_number.js | 2 +- .../lib/logstash/__tests__/pipelines.js | 2 +- .../public/services/__tests__/breadcrumbs.js | 2 +- .../services/__tests__/executor_provider.js | 2 +- .../public/views/__tests__/base_controller.js | 2 +- .../views/__tests__/base_table_controller.js | 2 +- .../monitoring/server/cloud/__tests__/aws.js | 2 +- .../server/cloud/__tests__/azure.js | 2 +- .../server/cloud/__tests__/cloud_detector.js | 2 +- .../server/cloud/__tests__/cloud_response.js | 2 +- .../server/cloud/__tests__/cloud_service.js | 2 +- .../server/cloud/__tests__/cloud_services.js | 2 +- .../monitoring/server/cloud/__tests__/gcp.js | 2 +- .../__tests__/alerts_cluster_search.js | 2 +- .../__tests__/alerts_clusters_aggregation.js | 2 +- .../cluster_alerts/__tests__/check_license.js | 2 +- .../__tests__/verify_monitoring_license.js | 2 +- .../es_client/__tests__/instantiate_client.js | 2 +- .../__tests__/bulk_uploader.js | 2 +- .../__tests__/check_for_email_value.js | 2 +- .../__tests__/get_default_admin_email.js | 2 +- .../ops_buffer/__tests__/event_roller.js | 2 +- .../ops_buffer/__tests__/map_requests.js | 2 +- .../__tests__/map_response_times.js | 2 +- .../server/lib/__tests__/calculate_auto.js | 2 +- .../lib/__tests__/calculate_availabiilty.js | 2 +- .../lib/__tests__/calculate_overall_status.js | 2 +- .../server/lib/__tests__/calculate_rate.js | 2 +- .../calculate_timeseries_interval.js | 2 +- .../server/lib/__tests__/ccs_utils.js | 2 +- .../server/lib/__tests__/create_query.js | 2 +- .../lib/__tests__/process_version_string.js | 2 +- .../lib/beats/__tests__/create_beats_query.js | 2 +- .../lib/beats/__tests__/get_beat_summary.js | 2 +- .../server/lib/beats/__tests__/get_beats.js | 2 +- .../beats/__tests__/get_beats_for_clusters.js | 2 +- .../lib/beats/__tests__/get_latest_stats.js | 2 +- .../server/lib/beats/__tests__/get_stats.js | 2 +- .../__tests__/flag_supported_clusters.js | 2 +- .../cluster/__tests__/get_cluster_status.js | 2 +- .../cluster/__tests__/get_clusters_state.js | 2 +- .../cluster/__tests__/get_clusters_stats.js | 2 +- .../__tests__/get_last_recovery.js | 2 +- .../elasticsearch/__tests__/get_ml_jobs.js | 2 +- .../indices/__tests__/get_index_summary.js | 2 +- .../indices/__tests__/get_indices.js | 2 +- .../nodes/__tests__/calculate_node_type.js | 2 +- .../nodes/__tests__/get_node_summary.js | 2 +- .../__tests__/get_node_type_class_label.js | 2 +- .../elasticsearch/nodes/__tests__/lookups.js | 2 +- .../shards/__tests__/get_shard_stats.js | 2 +- .../__tests__/normalize_shard_objects.js | 2 +- .../__tests__/cluster.js | 2 +- .../__tests__/find_reason.js | 2 +- .../elasticsearch_settings/__tests__/nodes.js | 2 +- .../lib/errors/__tests__/auth_errors.js | 2 +- .../lib/errors/__tests__/known_errors.js | 2 +- .../lib/kibana/__tests__/get_kibana_info.js | 2 +- .../lib/logstash/__tests__/get_node_info.js | 2 +- .../lib/logstash/__tests__/get_pipeline.js | 2 +- .../lib/logstash/__tests__/get_pipelines.js | 2 +- .../check_license/__tests__/check_license.js | 2 +- .../__tests__/wrap_custom_error.js | 2 +- .../error_wrappers/__tests__/wrap_es_error.js | 2 +- .../__tests__/wrap_unknown_error.js | 2 +- .../__tests__/is_es_error_factory.js | 2 +- .../__tests__/license_pre_routing_factory.js | 2 +- .../common/__tests__/export_types_registry.js | 2 +- .../csv/server/__tests__/execute_job.js | 2 +- .../csv/server/lib/__tests__/escape_value.js | 2 +- .../server/lib/__tests__/field_format_map.js | 2 +- .../csv/server/lib/__tests__/flatten_hit.js | 2 +- .../server/lib/__tests__/format_csv_values.js | 2 +- .../lib/__tests__/max_size_string_builder.js | 2 +- .../browsers/extract/__tests__/extract.js | 2 +- .../server/lib/__tests__/check_license.js | 2 +- .../__tests__/helpers/cancellation_token.js | 2 +- .../esqueue/__tests__/helpers/create_index.js | 2 +- .../lib/esqueue/__tests__/helpers/errors.js | 2 +- .../__tests__/helpers/index_timestamp.js | 2 +- .../server/lib/esqueue/__tests__/index.js | 2 +- .../server/lib/esqueue/__tests__/job.js | 2 +- .../server/lib/esqueue/__tests__/worker.js | 2 +- .../lib/validate/__tests__/validate_config.js | 2 +- .../__tests__/validate_max_content_length.js | 2 +- .../authorized_user_pre_routing.test.js | 2 +- .../lib/__tests__/jobs_compatibility.js | 2 +- .../check_license/__tests__/check_license.js | 2 +- .../__tests__/wrap_custom_error.js | 2 +- .../error_wrappers/__tests__/wrap_es_error.js | 2 +- .../__tests__/wrap_unknown_error.js | 2 +- .../__tests__/is_es_error_factory.js | 2 +- .../__tests__/license_pre_routing_factory.js | 2 +- .../public/__tests__/app_util.js | 2 +- .../profile_tree/__tests__/profile_tree.js | 2 +- .../public/filters/__tests__/ns_to_pretty.js | 2 +- .../server/lib/__tests__/check_license.js | 2 +- .../public/lib/__tests__/parse_next.js | 2 +- .../security/public/lib/__tests__/util.js | 2 +- .../server/lib/__tests__/auth_redirect.js | 2 +- .../lib/__tests__/auth_scope_service.js | 2 +- .../server/lib/__tests__/check_license.js | 2 +- .../security/server/lib/__tests__/errors.js | 2 +- .../server/lib/__tests__/parse_next.js | 2 +- .../server/lib/__tests__/validate_config.js | 2 +- .../authentication/__tests__/authenticator.js | 2 +- .../lib/authentication/__tests__/session.js | 2 +- .../providers/__tests__/basic.js | 2 +- .../providers/__tests__/token.js | 2 +- .../routes/api/v1/__tests__/authenticate.js | 2 +- .../server/routes/api/v1/__tests__/users.js | 2 +- .../server/lib/__tests__/inspect_settings.js | 2 +- .../watcher/__tests__/plugin_definition.js | 2 +- .../__tests__/get_action_type.js | 2 +- .../lib/get_moment/__tests__/get_moment.js | 2 +- .../__tests__/sortable_boolean.js | 2 +- .../check_license/__tests__/check_license.js | 2 +- .../__tests__/wrap_custom_error.js | 2 +- .../error_wrappers/__tests__/wrap_es_error.js | 2 +- .../__tests__/wrap_unknown_error.js | 2 +- .../__tests__/fetch_all_from_scroll.js | 2 +- .../__tests__/is_es_error_factory.js | 2 +- .../__tests__/license_pre_routing_factory.js | 2 +- .../action_status/__tests__/action_status.js | 2 +- .../__tests__/execute_details.js | 2 +- .../server/models/fields/__tests__/fields.js | 2 +- .../models/settings/__tests__/settings.js | 2 +- .../models/watch/__tests__/base_watch.js | 2 +- .../models/watch/__tests__/json_watch.js | 2 +- .../watch/__tests__/monitoring_watch.js | 2 +- .../models/watch/__tests__/threshold_watch.js | 2 +- .../server/models/watch/__tests__/watch.js | 2 +- .../__tests__/format_visualize_data.js | 2 +- .../__tests__/watch_history_item.js | 2 +- .../watch_status/__tests__/watch_status.js | 2 +- .../public/hacks/__tests__/fetch_telemetry.js | 2 +- .../welcome_banner/__tests__/click_banner.js | 2 +- .../__tests__/handle_old_settings.js | 2 +- .../welcome_banner/__tests__/render_banner.js | 2 +- .../__tests__/should_show_banner.js | 2 +- .../public/services/__tests__/xpack_info.js | 2 +- .../__tests__/xpack_info_signature.js | 2 +- .../lib/__tests__/call_cluster_factory.js | 2 +- .../__tests__/inject_xpack_info_signature.js | 2 +- .../lib/__tests__/replace_injected_vars.js | 2 +- .../server/lib/__tests__/xpack_info.js | 2 +- .../local/__tests__/get_cluster_info.js | 2 +- .../local/__tests__/get_cluster_stats.js | 2 +- .../local/__tests__/get_local_stats.js | 2 +- .../telemetry/local/__tests__/get_xpack.js | 2 +- .../monitoring/__tests__/create_query.js | 2 +- .../monitoring/__tests__/get_all_stats.js | 2 +- .../monitoring/__tests__/get_beats_stats.js | 2 +- .../monitoring/__tests__/get_cluster_uuids.js | 2 +- .../monitoring/__tests__/get_es_stats.js | 2 +- .../__tests__/get_high_level_stats.js | 2 +- .../monitoring/__tests__/get_kibana_stats.js | 2 +- .../routes/api/v1/__tests__/xpack_info.js | 2 +- .../api/v1/telemetry/__tests__/telemetry.js | 2 +- .../lib/__tests__/key_case_converter.js | 2 +- x-pack/server/lib/__tests__/kibana_state.js | 2 +- .../lib/__tests__/mirror_plugin_status.js | 2 +- .../__tests__/wrap_custom_error.js | 2 +- .../error_wrappers/__tests__/wrap_es_error.js | 2 +- .../__tests__/wrap_unknown_error.js | 2 +- .../__tests__/is_es_error_factory.js | 2 +- .../__tests__/license_pre_routing_factory.js | 2 +- .../apis/beats/assign_tags_to_beats.js | 2 +- .../apis/beats/create_enrollment_tokens.js | 2 +- .../api_integration/apis/beats/enroll_beat.js | 2 +- .../api_integration/apis/beats/get_beat.js | 2 +- .../api_integration/apis/beats/list_beats.js | 2 +- .../apis/beats/remove_tags_from_beats.js | 2 +- .../api_integration/apis/beats/set_config.js | 2 +- .../api_integration/apis/beats/set_tag.js | 2 +- .../api_integration/apis/beats/update_beat.js | 2 +- .../api_integration/apis/es/has_privileges.js | 2 +- .../apis/es/post_privileges.js | 2 +- .../api_integration/apis/infra/log_entries.ts | 2 +- .../api_integration/apis/infra/log_item.ts | 2 +- .../api_integration/apis/infra/log_summary.ts | 2 +- .../apis/infra/logs_without_millis.ts | 2 +- .../api_integration/apis/infra/metadata.ts | 2 +- .../api_integration/apis/infra/metrics.ts | 2 +- .../api_integration/apis/infra/sources.ts | 2 +- .../test/api_integration/apis/infra/waffle.ts | 2 +- .../kibana/kql_telemetry/kql_telemetry.js | 2 +- .../apis/kibana/stats/stats.js | 2 +- .../apis/logstash/cluster/load.js | 2 +- .../apis/logstash/pipeline/load.js | 2 +- .../apis/logstash/pipeline/save.js | 2 +- .../apis/logstash/pipelines/list.js | 2 +- .../auto_follow_pattern.js | 2 +- .../follower_indices.js | 2 +- .../remote_clusters/remote_clusters.js | 2 +- .../rollup/index_patterns_extensions.js | 2 +- .../apis/management/rollup/rollup.js | 2 +- .../apis/management/rollup/rollup_search.js | 2 +- .../api_integration/apis/maps/migrations.js | 2 +- .../apis/monitoring/apm/instance.js | 2 +- .../apis/monitoring/apm/instances.js | 2 +- .../apis/monitoring/apm/overview.js | 2 +- .../apis/monitoring/beats/detail.js | 2 +- .../apis/monitoring/beats/list.js | 2 +- .../apis/monitoring/beats/overview.js | 2 +- .../apis/monitoring/cluster/list.js | 2 +- .../apis/monitoring/cluster/overview.js | 2 +- .../apis/monitoring/common/mappings_exist.js | 2 +- .../apis/monitoring/elasticsearch/ccr.js | 2 +- .../monitoring/elasticsearch/ccr_shard.js | 2 +- .../monitoring/elasticsearch/index_detail.js | 2 +- .../apis/monitoring/elasticsearch/indices.js | 2 +- .../monitoring/elasticsearch/node_detail.js | 2 +- .../elasticsearch/node_detail_advanced.js | 2 +- .../apis/monitoring/elasticsearch/nodes.js | 2 +- .../apis/monitoring/elasticsearch/overview.js | 2 +- .../elasticsearch_settings/check_cluster.js | 2 +- .../elasticsearch_settings/check_nodes.js | 2 +- .../set_collection_enabled.js | 2 +- .../set_collection_interval.js | 2 +- .../apis/monitoring/kibana/instance.js | 2 +- .../apis/monitoring/kibana/listing.js | 2 +- .../apis/monitoring/kibana/overview.js | 2 +- .../apis/monitoring/logstash/node_detail.js | 2 +- .../apis/monitoring/logstash/nodes.js | 2 +- .../apis/monitoring/logstash/overview.js | 2 +- .../monitoring/standalone_cluster/cluster.js | 2 +- .../monitoring/standalone_cluster/clusters.js | 2 +- .../apis/security/basic_login.js | 2 +- .../api_integration/apis/security/roles.js | 2 +- .../apis/uptime/get_all_pings.js | 2 +- .../apis/uptime/graphql/doc_count.js | 2 +- .../apis/uptime/graphql/error_list.js | 2 +- .../apis/uptime/graphql/filter_bar.js | 2 +- .../apis/uptime/graphql/monitor_charts.js | 2 +- .../apis/uptime/graphql/monitor_list.js | 2 +- .../apis/uptime/graphql/monitor_status_bar.js | 2 +- .../apis/uptime/graphql/ping_list.js | 2 +- .../apis/uptime/graphql/snapshot.js | 2 +- .../apis/xpack_main/settings/settings.js | 2 +- .../apis/xpack_main/telemetry/telemetry.js | 2 +- .../xpack_main/telemetry/telemetry_local.js | 2 +- .../test/functional/apps/canvas/smoke_test.js | 2 +- .../dashboard_mode/dashboard_view_mode.js | 2 +- x-pack/test/functional/apps/graph/graph.js | 2 +- .../apps/logstash/pipeline_create.js | 2 +- .../functional/apps/logstash/pipeline_list.js | 2 +- .../functional/apps/maps/add_layer_panel.js | 2 +- .../apps/maps/embeddable/dashboard.js | 2 +- .../apps/maps/es_geo_grid_source.js | 2 +- .../functional/apps/maps/es_search_source.js | 2 +- x-pack/test/functional/apps/maps/joins.js | 2 +- .../test/functional/apps/maps/layer_errors.js | 2 +- .../test/functional/apps/maps/sample_data.js | 2 +- .../apps/maps/saved_object_management.js | 2 +- .../apps/monitoring/beats/beat_detail.js | 2 +- .../apps/monitoring/beats/cluster.js | 2 +- .../apps/monitoring/beats/listing.js | 2 +- .../apps/monitoring/beats/overview.js | 2 +- .../apps/monitoring/cluster/alerts.js | 2 +- .../apps/monitoring/cluster/list.js | 2 +- .../apps/monitoring/cluster/overview.js | 2 +- .../monitoring/elasticsearch/index_detail.js | 2 +- .../apps/monitoring/elasticsearch/indices.js | 2 +- .../monitoring/elasticsearch/node_detail.js | 2 +- .../apps/monitoring/elasticsearch/nodes.js | 2 +- .../apps/monitoring/elasticsearch/overview.js | 2 +- .../apps/monitoring/elasticsearch/shards.js | 2 +- .../monitoring/enable_monitoring/index.js | 2 +- .../apps/monitoring/kibana/instance.js | 2 +- .../apps/monitoring/kibana/instances.js | 2 +- .../apps/monitoring/kibana/overview.js | 2 +- .../apps/monitoring/logstash/pipelines.js | 2 +- .../functional/apps/rollup_job/rollup_jobs.js | 2 +- .../apps/security/doc_level_security_roles.js | 2 +- .../apps/security/field_level_security.js | 2 +- .../functional/apps/security/management.js | 2 +- .../functional/apps/security/rbac_phase1.js | 2 +- .../apps/security/secure_roles_perm.js | 2 +- .../test/functional/apps/security/security.js | 2 +- .../functional/apps/security/user_email.js | 2 +- x-pack/test/functional/apps/security/users.js | 2 +- .../functional/apps/watcher/watcher_test.js | 2 +- .../page_objects/accountsetting_page.js | 2 +- .../functional/page_objects/rollup_page.js | 2 +- .../page_objects/space_selector_page.js | 2 +- .../functional/page_objects/status_page.js | 2 +- .../page_objects/upgrade_assistant.js | 2 +- .../test/functional/services/grok_debugger.js | 2 +- .../services/monitoring/cluster_overview.js | 2 +- .../functional/services/pipeline_editor.js | 2 +- .../task_manager/task_manager_integration.js | 2 +- x-pack/test/reporting/api/usage.js | 2 +- x-pack/test/reporting/functional/reporting.js | 2 +- .../test/reporting/services/reporting_api.js | 2 +- .../apis/security/saml_login.js | 2 +- .../common/suites/bulk_create.ts | 2 +- .../common/suites/bulk_get.ts | 2 +- .../common/suites/create.ts | 2 +- .../common/suites/delete.ts | 2 +- .../common/suites/export.ts | 2 +- .../common/suites/find.ts | 2 +- .../common/suites/get.ts | 2 +- .../common/suites/import.ts | 2 +- .../common/suites/resolve_import_errors.ts | 2 +- .../common/suites/update.ts | 2 +- .../spaces_only/apis/bulk_create.ts | 2 +- .../spaces_only/apis/create.ts | 2 +- .../common/suites/create.ts | 2 +- .../common/suites/delete.ts | 2 +- .../common/suites/get.ts | 2 +- .../common/suites/get_all.ts | 2 +- .../common/suites/select.ts | 2 +- .../common/suites/update.ts | 2 +- x-pack/test/tsconfig.json | 1 - .../upgrade_assistant/reindexing.js | 2 +- x-pack/tsconfig.json | 3 +- yarn.lock | 5 - 1117 files changed, 2679 insertions(+), 1341 deletions(-) create mode 100644 packages/kbn-eslint-plugin-eslint/rules/module_migration.js create mode 100644 packages/kbn-expect/LICENSE.txt create mode 100644 packages/kbn-expect/README.md create mode 100644 packages/kbn-expect/expect.js create mode 100644 packages/kbn-expect/expect.js.d.ts create mode 100644 packages/kbn-expect/package.json create mode 100644 packages/kbn-expect/tsconfig.json delete mode 100644 packages/kbn-test/types/expect.js.d.ts create mode 100644 src/dev/tslint/rules/moduleMigrationRule.js diff --git a/.eslintrc.js b/.eslintrc.js index 8bfa6c5959668..ea3ad6ec3ccdc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -47,6 +47,15 @@ module.exports = { rules: { 'no-restricted-imports': [2, restrictedModules], 'no-restricted-modules': [2, restrictedModules], + '@kbn/eslint/module_migration': [ + 'error', + [ + { + from: 'expect.js', + to: '@kbn/expect', + }, + ], + ], }, overrides: [ diff --git a/TYPESCRIPT.md b/TYPESCRIPT.md index 68cb32ce36c74..66b2fd0e77c68 100644 --- a/TYPESCRIPT.md +++ b/TYPESCRIPT.md @@ -111,7 +111,7 @@ If yarn doesn't find the module it may not have types. For example, our `rison_ 1. Contribute types into the DefinitelyTyped repo itself, or 2. Create a top level `types` folder and point to that in the tsconfig. For example, Infra team already handled this for `rison_node` and added: `x-pack/plugins/infra/types/rison_node.d.ts`. Other code uses it too so we will need to pull it up. Or, -3. Add a `// @ts-ignore` line above the import. This should be used minimally, the above options are better. However, sometimes you have to resort to this method. For example, the `expect.js` module will require this line. We don't have type definitions installed for this library. Installing these types would conflict with the jest typedefs for expect, and since they aren't API compatible with each other, it's not possible to make both test frameworks happy. Since we are moving from mocha => jest, we don't see this is a big issue. +3. Add a `// @ts-ignore` line above the import. This should be used minimally, the above options are better. However, sometimes you have to resort to this method. ### TypeScripting react files diff --git a/docs/development/core/development-functional-tests.asciidoc b/docs/development/core/development-functional-tests.asciidoc index 813c4fa929aa9..8d1238993b7cb 100644 --- a/docs/development/core/development-functional-tests.asciidoc +++ b/docs/development/core/development-functional-tests.asciidoc @@ -82,7 +82,7 @@ Use the `--help` flag for more options. [float] ===== Environment -The tests are written in https://mochajs.org[mocha] using https://github.com/Automattic/expect.js[expect] for assertions. +The tests are written in https://mochajs.org[mocha] using https://github.com/elastic/kibana/tree/master/packages/kbn-expect[@kbn/expect] for assertions. We use https://sites.google.com/a/chromium.org/chromedriver/[chromedriver], https://theintern.github.io/leadfoot[leadfoot], and https://github.com/theintern/digdug[digdug] for automating Chrome. When the `FunctionalTestRunner` launches, digdug opens a `Tunnel` which starts chromedriver and a stripped-down instance of Chrome. It also creates an instance of https://theintern.github.io/leadfoot/module-leadfoot_Command.html[Leadfoot's `Command`] class, which is available via the `remote` service. The `remote` communicates to Chrome through the digdug `Tunnel`. See the https://theintern.github.io/leadfoot/module-leadfoot_Command.html[leadfoot/Command API] docs for all the commands you can use with `remote`. @@ -122,11 +122,11 @@ A test suite is a collection of tests defined by calling `describe()`, and then [float] ===== Anatomy of a test file -The annotated example file below shows the basic structure every test suite uses. It starts by importing https://github.com/Automattic/expect.js[`expect.js`] and defining its default export: an anonymous Test Provider. The test provider then destructures the Provider API for the `getService()` and `getPageObjects()` functions. It uses these functions to collect the dependencies of this suite. The rest of the test file will look pretty normal to mocha.js users. `describe()`, `it()`, `before()` and the lot are used to define suites that happen to automate a browser via services and objects of type `PageObject`. +The annotated example file below shows the basic structure every test suite uses. It starts by importing https://github.com/elastic/kibana/tree/master/packages/kbn-expect[`@kbn/expect`] and defining its default export: an anonymous Test Provider. The test provider then destructures the Provider API for the `getService()` and `getPageObjects()` functions. It uses these functions to collect the dependencies of this suite. The rest of the test file will look pretty normal to mocha.js users. `describe()`, `it()`, `before()` and the lot are used to define suites that happen to automate a browser via services and objects of type `PageObject`. ["source","js"] ---- -import expect from 'expect.js'; +import expect from '@kbn/expect'; // test files must `export default` a function that defines a test suite export default function ({ getService, getPageObject }) { diff --git a/package.json b/package.json index fee468ac45ac8..30bd3f9d52897 100644 --- a/package.json +++ b/package.json @@ -258,6 +258,7 @@ "@kbn/es": "1.0.0", "@kbn/eslint-import-resolver-kibana": "2.0.0", "@kbn/eslint-plugin-eslint": "1.0.0", + "@kbn/expect": "1.0.0", "@kbn/plugin-generator": "1.0.0", "@kbn/test": "1.0.0", "@octokit/rest": "^15.10.0", @@ -346,7 +347,6 @@ "eslint-plugin-prefer-object-spread": "^1.2.1", "eslint-plugin-prettier": "^2.6.2", "eslint-plugin-react": "^7.11.1", - "expect.js": "0.3.1", "faker": "1.1.0", "fetch-mock": "7.3.0", "geckodriver": "1.12.2", diff --git a/packages/elastic-datemath/test/index.js b/packages/elastic-datemath/test/index.js index 2028c2c0cedce..582b331eac7e8 100644 --- a/packages/elastic-datemath/test/index.js +++ b/packages/elastic-datemath/test/index.js @@ -20,7 +20,7 @@ import dateMath from '../src/index'; import moment from 'moment'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; /** * Require a new instance of the moment library, bypassing the require cache. diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json index 3775cc06d3b11..af39ffecf6690 100644 --- a/packages/kbn-dev-utils/package.json +++ b/packages/kbn-dev-utils/package.json @@ -20,8 +20,8 @@ }, "devDependencies": { "@kbn/babel-preset": "1.0.0", + "@kbn/expect": "1.0.0", "babel-cli": "^6.26.0", - "chance": "1.0.6", - "expect.js": "0.3.1" + "chance": "1.0.6" } } diff --git a/packages/kbn-es-query/package.json b/packages/kbn-es-query/package.json index 09682ae7ede31..ff68adeac8631 100644 --- a/packages/kbn-es-query/package.json +++ b/packages/kbn-es-query/package.json @@ -22,8 +22,8 @@ "@babel/preset-typescript": "^7.3.3", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", + "@kbn/expect": "1.0.0", "del": "^3.0.0", - "expect.js": "0.3.1", "getopts": "^2.2.3", "supports-color": "^6.1.0", "typescript": "^3.3.3333" diff --git a/packages/kbn-es-query/src/es_query/__tests__/_migrate_filter.js b/packages/kbn-es-query/src/es_query/__tests__/_migrate_filter.js index 0faa0d6de6464..d9f559987f58b 100644 --- a/packages/kbn-es-query/src/es_query/__tests__/_migrate_filter.js +++ b/packages/kbn-es-query/src/es_query/__tests__/_migrate_filter.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; import { migrateFilter } from '../migrate_filter'; diff --git a/packages/kbn-es-query/src/es_query/__tests__/build_es_query.js b/packages/kbn-es-query/src/es_query/__tests__/build_es_query.js index 951a9e03cb9fe..879fb1cd6c45f 100644 --- a/packages/kbn-es-query/src/es_query/__tests__/build_es_query.js +++ b/packages/kbn-es-query/src/es_query/__tests__/build_es_query.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { buildEsQuery } from '../build_es_query'; import indexPattern from '../../__fixtures__/index_pattern_response.json'; import { fromKueryExpression, toElasticsearchQuery } from '../../kuery'; diff --git a/packages/kbn-es-query/src/es_query/__tests__/decorate_query.js b/packages/kbn-es-query/src/es_query/__tests__/decorate_query.js index 5b3e64bb229ad..447a875e9eadc 100644 --- a/packages/kbn-es-query/src/es_query/__tests__/decorate_query.js +++ b/packages/kbn-es-query/src/es_query/__tests__/decorate_query.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { decorateQuery } from '../decorate_query'; describe('Query decorator', function () { diff --git a/packages/kbn-es-query/src/es_query/__tests__/filter_matches_index.js b/packages/kbn-es-query/src/es_query/__tests__/filter_matches_index.js index fe7da03731263..1c43230aeea30 100644 --- a/packages/kbn-es-query/src/es_query/__tests__/filter_matches_index.js +++ b/packages/kbn-es-query/src/es_query/__tests__/filter_matches_index.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { filterMatchesIndex } from '../filter_matches_index'; describe('filterMatchesIndex', function () { diff --git a/packages/kbn-es-query/src/es_query/__tests__/from_filters.js b/packages/kbn-es-query/src/es_query/__tests__/from_filters.js index 8d1b103c8f66c..53016f33dc6cd 100644 --- a/packages/kbn-es-query/src/es_query/__tests__/from_filters.js +++ b/packages/kbn-es-query/src/es_query/__tests__/from_filters.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { buildQueryFromFilters } from '../from_filters'; describe('build query', function () { diff --git a/packages/kbn-es-query/src/es_query/__tests__/from_kuery.js b/packages/kbn-es-query/src/es_query/__tests__/from_kuery.js index 7f4952fbbfc48..7c285a4416abc 100644 --- a/packages/kbn-es-query/src/es_query/__tests__/from_kuery.js +++ b/packages/kbn-es-query/src/es_query/__tests__/from_kuery.js @@ -19,7 +19,7 @@ import { buildQueryFromKuery } from '../from_kuery'; import indexPattern from '../../__fixtures__/index_pattern_response.json'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { fromKueryExpression, toElasticsearchQuery } from '../../kuery'; describe('build query', function () { diff --git a/packages/kbn-es-query/src/es_query/__tests__/from_lucene.js b/packages/kbn-es-query/src/es_query/__tests__/from_lucene.js index 5da5075925dbe..7a4b6f7b359f5 100644 --- a/packages/kbn-es-query/src/es_query/__tests__/from_lucene.js +++ b/packages/kbn-es-query/src/es_query/__tests__/from_lucene.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { buildQueryFromLucene } from '../from_lucene'; import { decorateQuery } from '../decorate_query'; import { luceneStringToDsl } from '../lucene_string_to_dsl'; diff --git a/packages/kbn-es-query/src/es_query/__tests__/lucene_string_to_dsl.js b/packages/kbn-es-query/src/es_query/__tests__/lucene_string_to_dsl.js index 67908f28b7330..04f6209ce6665 100644 --- a/packages/kbn-es-query/src/es_query/__tests__/lucene_string_to_dsl.js +++ b/packages/kbn-es-query/src/es_query/__tests__/lucene_string_to_dsl.js @@ -18,7 +18,7 @@ */ import { luceneStringToDsl } from '../lucene_string_to_dsl'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('build query', function () { diff --git a/packages/kbn-es-query/src/filters/__tests__/phrase.js b/packages/kbn-es-query/src/filters/__tests__/phrase.js index 0fd2a5fbd0760..6b611fdf074f2 100644 --- a/packages/kbn-es-query/src/filters/__tests__/phrase.js +++ b/packages/kbn-es-query/src/filters/__tests__/phrase.js @@ -19,7 +19,7 @@ import { buildInlineScriptForPhraseFilter, buildPhraseFilter } from '../phrase'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; import indexPattern from '../../__fixtures__/index_pattern_response.json'; import filterSkeleton from '../../__fixtures__/filter_skeleton'; diff --git a/packages/kbn-es-query/src/filters/__tests__/query.js b/packages/kbn-es-query/src/filters/__tests__/query.js index 62f7a898140c1..8b774f05c29d3 100644 --- a/packages/kbn-es-query/src/filters/__tests__/query.js +++ b/packages/kbn-es-query/src/filters/__tests__/query.js @@ -19,7 +19,7 @@ import { buildQueryFilter } from '../query'; import { cloneDeep } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import indexPattern from '../../__fixtures__/index_pattern_response.json'; import filterSkeleton from '../../__fixtures__/filter_skeleton'; diff --git a/packages/kbn-es-query/src/filters/__tests__/range.js b/packages/kbn-es-query/src/filters/__tests__/range.js index 6fe914475836f..595b386a32ab8 100644 --- a/packages/kbn-es-query/src/filters/__tests__/range.js +++ b/packages/kbn-es-query/src/filters/__tests__/range.js @@ -18,7 +18,7 @@ */ import { buildRangeFilter } from '../range'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; import indexPattern from '../../__fixtures__/index_pattern_response.json'; import filterSkeleton from '../../__fixtures__/filter_skeleton'; diff --git a/packages/kbn-es-query/src/kuery/ast/__tests__/ast.js b/packages/kbn-es-query/src/kuery/ast/__tests__/ast.js index 1107d1eea04d6..96039526752d4 100644 --- a/packages/kbn-es-query/src/kuery/ast/__tests__/ast.js +++ b/packages/kbn-es-query/src/kuery/ast/__tests__/ast.js @@ -18,7 +18,7 @@ */ import * as ast from '../ast'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { nodeTypes } from '../../node_types/index'; import indexPatternResponse from '../../../__fixtures__/index_pattern_response.json'; diff --git a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/exists.js b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/exists.js index e4eff469933db..6c149b6b8a98d 100644 --- a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/exists.js +++ b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/exists.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { convertExistsFilter } from '../exists'; describe('filter to kuery migration', function () { diff --git a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/filter_to_kuery.js b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/filter_to_kuery.js index f21675fdd7de4..1e5656f85eb89 100644 --- a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/filter_to_kuery.js +++ b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/filter_to_kuery.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { filterToKueryAST } from '../filter_to_kuery'; describe('filter to kuery migration', function () { diff --git a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/geo_bounding_box.js b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/geo_bounding_box.js index 6842e2b8a3dd0..e4cb6d30bbf48 100644 --- a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/geo_bounding_box.js +++ b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/geo_bounding_box.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { convertGeoBoundingBox } from '../geo_bounding_box'; describe('filter to kuery migration', function () { diff --git a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/geo_polygon.js b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/geo_polygon.js index 0228a73a99512..e1b2a09edaba3 100644 --- a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/geo_polygon.js +++ b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/geo_polygon.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { convertGeoPolygon } from '../geo_polygon'; describe('filter to kuery migration', function () { diff --git a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/phrase.js b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/phrase.js index 4e3df8d6ddec4..b2a7c097a3f95 100644 --- a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/phrase.js +++ b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/phrase.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { convertPhraseFilter } from '../phrase'; describe('filter to kuery migration', function () { diff --git a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/range.js b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/range.js index 5583a585e35eb..2cad37cc0ad3a 100644 --- a/packages/kbn-es-query/src/kuery/filter_migration/__tests__/range.js +++ b/packages/kbn-es-query/src/kuery/filter_migration/__tests__/range.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { convertRangeFilter } from '../range'; describe('filter to kuery migration', function () { diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/and.js b/packages/kbn-es-query/src/kuery/functions/__tests__/and.js index 2a29e01d2b50b..5a0d3a9cd58b2 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/and.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/and.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as and from '../and'; import { nodeTypes } from '../../node_types'; import * as ast from '../../ast'; diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js b/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js index 694c044bd49ff..0eaa69a3243e0 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as exists from '../exists'; import { nodeTypes } from '../../node_types'; import _ from 'lodash'; diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js index 28aee22dd94d9..2f8b784d6f6e8 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as geoBoundingBox from '../geo_bounding_box'; import { nodeTypes } from '../../node_types'; import indexPatternResponse from '../../../__fixtures__/index_pattern_response.json'; diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js index 7f01b84eef93d..1c6a2e0e47fde 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as geoPolygon from '../geo_polygon'; import { nodeTypes } from '../../node_types'; import indexPatternResponse from '../../../__fixtures__/index_pattern_response.json'; diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/is.js b/packages/kbn-es-query/src/kuery/functions/__tests__/is.js index 5018b18c2e8c2..7ceac9b605db4 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/is.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/is.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as is from '../is'; import { nodeTypes } from '../../node_types'; import indexPatternResponse from '../../../__fixtures__/index_pattern_response.json'; diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/not.js b/packages/kbn-es-query/src/kuery/functions/__tests__/not.js index f397382b543e8..6b5b50e15524d 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/not.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/not.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as not from '../not'; import { nodeTypes } from '../../node_types'; import * as ast from '../../ast'; diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/or.js b/packages/kbn-es-query/src/kuery/functions/__tests__/or.js index 49a2b21446b02..3b5bf27f2d8cb 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/or.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/or.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as or from '../or'; import { nodeTypes } from '../../node_types'; import * as ast from '../../ast'; diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/range.js b/packages/kbn-es-query/src/kuery/functions/__tests__/range.js index 92108a8fb8674..a8c0b8157405d 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/range.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/range.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as range from '../range'; import { nodeTypes } from '../../node_types'; import indexPatternResponse from '../../../__fixtures__/index_pattern_response.json'; diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/utils/get_fields.js b/packages/kbn-es-query/src/kuery/functions/__tests__/utils/get_fields.js index 501f61a92b5e2..7718479130a8a 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/utils/get_fields.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/utils/get_fields.js @@ -18,7 +18,7 @@ */ import { getFields } from '../../utils/get_fields'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import indexPatternResponse from '../../../../__fixtures__/index_pattern_response.json'; import { nodeTypes } from '../../..'; diff --git a/packages/kbn-es-query/src/kuery/node_types/__tests__/function.js b/packages/kbn-es-query/src/kuery/node_types/__tests__/function.js index 4e7e1d9254365..2ccb3bd5991d8 100644 --- a/packages/kbn-es-query/src/kuery/node_types/__tests__/function.js +++ b/packages/kbn-es-query/src/kuery/node_types/__tests__/function.js @@ -19,7 +19,7 @@ import * as functionType from '../function'; import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as isFunction from '../../functions/is'; import indexPatternResponse from '../../../__fixtures__/index_pattern_response.json'; diff --git a/packages/kbn-es-query/src/kuery/node_types/__tests__/literal.js b/packages/kbn-es-query/src/kuery/node_types/__tests__/literal.js index 570e21dbf3899..25fe2bcc45a45 100644 --- a/packages/kbn-es-query/src/kuery/node_types/__tests__/literal.js +++ b/packages/kbn-es-query/src/kuery/node_types/__tests__/literal.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as literal from '../literal'; describe('kuery node types', function () { diff --git a/packages/kbn-es-query/src/kuery/node_types/__tests__/named_arg.js b/packages/kbn-es-query/src/kuery/node_types/__tests__/named_arg.js index 6a7d8cb3abb81..cfb8f6d5274db 100644 --- a/packages/kbn-es-query/src/kuery/node_types/__tests__/named_arg.js +++ b/packages/kbn-es-query/src/kuery/node_types/__tests__/named_arg.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as namedArg from '../named_arg'; import { nodeTypes } from '../../node_types'; diff --git a/packages/kbn-es-query/src/kuery/node_types/__tests__/wildcard.js b/packages/kbn-es-query/src/kuery/node_types/__tests__/wildcard.js index f9ad1bf1dccb6..0c4379378c6d6 100644 --- a/packages/kbn-es-query/src/kuery/node_types/__tests__/wildcard.js +++ b/packages/kbn-es-query/src/kuery/node_types/__tests__/wildcard.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as wildcard from '../wildcard'; describe('kuery node types', function () { diff --git a/packages/kbn-eslint-plugin-eslint/index.js b/packages/kbn-eslint-plugin-eslint/index.js index 70b42d92d4b74..2840986ddf17c 100644 --- a/packages/kbn-eslint-plugin-eslint/index.js +++ b/packages/kbn-eslint-plugin-eslint/index.js @@ -22,5 +22,6 @@ module.exports = { 'require-license-header': require('./rules/require_license_header'), 'disallow-license-headers': require('./rules/disallow_license_headers'), 'no-default-export': require('./rules/no_default_export'), + module_migration: require('./rules/module_migration'), }, }; diff --git a/packages/kbn-eslint-plugin-eslint/rules/module_migration.js b/packages/kbn-eslint-plugin-eslint/rules/module_migration.js new file mode 100644 index 0000000000000..4f4f1b0f31c96 --- /dev/null +++ b/packages/kbn-eslint-plugin-eslint/rules/module_migration.js @@ -0,0 +1,82 @@ +/* + * 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. + */ + +function checkModuleNameNode(context, mappings, node) { + const mapping = mappings.find( + mapping => mapping.from === node.value || mapping.from.startsWith(node.value + '/') + ); + + if (!mapping) { + return; + } + + const newSource = node.value.replace(mapping.from, mapping.to); + context.report({ + message: `Imported module "${node.value}" should be "${newSource}"`, + loc: node.loc, + fix(fixer) { + return fixer.replaceText(node, `'${newSource}'`); + }, + }); +} + +module.exports = { + meta: { + fixable: 'code', + schema: [ + { + type: 'array', + items: { + type: 'object', + properties: { + from: { + type: 'string', + }, + to: { + type: 'string', + }, + }, + required: ['from', 'to'], + additionalProperties: false, + }, + default: [], + minItems: 1, + }, + ], + }, + create: context => { + const mappings = context.options[0]; + + return { + ImportDeclaration(node) { + checkModuleNameNode(context, mappings, node.source); + }, + CallExpression(node) { + if ( + node.callee.type === 'Identifier' && + node.callee.name === 'require' && + node.arguments.length === 1 && + node.arguments[0].type === 'Literal' + ) { + checkModuleNameNode(context, mappings, node.arguments[0]); + } + }, + }; + }, +}; diff --git a/packages/kbn-expect/LICENSE.txt b/packages/kbn-expect/LICENSE.txt new file mode 100644 index 0000000000000..0f4acd44d7655 --- /dev/null +++ b/packages/kbn-expect/LICENSE.txt @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2011 Guillermo Rauch + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/kbn-expect/README.md b/packages/kbn-expect/README.md new file mode 100644 index 0000000000000..51cf5bcf2ee52 --- /dev/null +++ b/packages/kbn-expect/README.md @@ -0,0 +1,191 @@ +> NOTE: This is a local fork of https://github.com/Automattic/expect.js + +# @kbn/expect + +Minimalistic BDD assertion toolkit based on +[should.js](http://github.com/visionmedia/should.js) + +```js +expect(window.r).to.be(undefined); +expect({ a: 'b' }).to.eql({ a: 'b' }) +expect(5).to.be.a('number'); +expect([]).to.be.an('array'); +expect(window).not.to.be.an(Image); +``` + +## Features + +- Cross-browser: works on IE6+, Firefox, Safari, Chrome, Opera. +- Compatible with all test frameworks. +- Node.JS ready (`require('@kbn/expect')`). + +## API + +**ok**: asserts that the value is _truthy_ or not + +```js +expect(1).to.be.ok(); +expect(true).to.be.ok(); +expect({}).to.be.ok(); +expect(0).to.not.be.ok(); +``` + +**be** / **equal**: asserts `===` equality + +```js +expect(1).to.be(1) +expect(NaN).not.to.equal(NaN); +expect(1).not.to.be(true) +expect('1').to.not.be(1); +``` + +**eql**: asserts loose equality that works with objects + +```js +expect({ a: 'b' }).to.eql({ a: 'b' }); +expect(1).to.eql('1'); +``` + +**a**/**an**: asserts `typeof` with support for `array` type and `instanceof` + +```js +// typeof with optional `array` +expect(5).to.be.a('number'); +expect([]).to.be.an('array'); // works +expect([]).to.be.an('object'); // works too, since it uses `typeof` + +// constructors +expect([]).to.be.an(Array); +expect(tobi).to.be.a(Ferret); +expect(person).to.be.a(Mammal); +``` + +**match**: asserts `String` regular expression match + +```js +expect(program.version).to.match(/[0-9]+\.[0-9]+\.[0-9]+/); +``` + +**contain**: asserts indexOf for an array or string + +```js +expect([1, 2]).to.contain(1); +expect('hello world').to.contain('world'); +``` + +**length**: asserts array `.length` + +```js +expect([]).to.have.length(0); +expect([1,2,3]).to.have.length(3); +``` + +**empty**: asserts that an array is empty or not + +```js +expect([]).to.be.empty(); +expect({}).to.be.empty(); +expect({ length: 0, duck: 'typing' }).to.be.empty(); +expect({ my: 'object' }).to.not.be.empty(); +expect([1,2,3]).to.not.be.empty(); +``` + +**property**: asserts presence of an own property (and value optionally) + +```js +expect(window).to.have.property('expect') +expect(window).to.have.property('expect', expect) +expect({a: 'b'}).to.have.property('a'); +``` + +**key**/**keys**: asserts the presence of a key. Supports the `only` modifier + +```js +expect({ a: 'b' }).to.have.key('a'); +expect({ a: 'b', c: 'd' }).to.only.have.keys('a', 'c'); +expect({ a: 'b', c: 'd' }).to.only.have.keys(['a', 'c']); +expect({ a: 'b', c: 'd' }).to.not.only.have.key('a'); +``` + +**throw**/**throwException**/**throwError**: asserts that the `Function` throws or not when called + +```js +expect(fn).to.throw(); // synonym of throwException +expect(fn).to.throwError(); // synonym of throwException +expect(fn).to.throwException(function (e) { // get the exception object + expect(e).to.be.a(SyntaxError); +}); +expect(fn).to.throwException(/matches the exception message/); +expect(fn2).to.not.throwException(); +``` + +**withArgs**: creates anonymous function to call fn with arguments + +```js +expect(fn).withArgs(invalid, arg).to.throwException(); +expect(fn).withArgs(valid, arg).to.not.throwException(); +``` + +**within**: asserts a number within a range + +```js +expect(1).to.be.within(0, Infinity); +``` + +**greaterThan**/**above**: asserts `>` + +```js +expect(3).to.be.above(0); +expect(5).to.be.greaterThan(3); +``` + +**lessThan**/**below**: asserts `<` + +```js +expect(0).to.be.below(3); +expect(1).to.be.lessThan(3); +``` + +**fail**: explicitly forces failure. + +```js +expect().fail() +expect().fail("Custom failure message") +``` + +## Using with a test framework + +For example, if you create a test suite with +[mocha](http://github.com/visionmedia/mocha). + +Let's say we wanted to test the following program: + +**math.js** + +```js +function add (a, b) { return a + b; }; +``` + +Our test file would look like this: + +```js +describe('test suite', function () { + it('should expose a function', function () { + expect(add).to.be.a('function'); + }); + + it('should do math', function () { + expect(add(1, 3)).to.equal(4); + }); +}); +``` + +If a certain expectation fails, an exception will be raised which gets captured +and shown/processed by the test runner. + +## Differences with should.js + +- No need for static `should` methods like `should.strictEqual`. For example, + `expect(obj).to.be(undefined)` works well. +- Some API simplifications / changes. +- API changes related to browser compatibility. diff --git a/packages/kbn-expect/expect.js b/packages/kbn-expect/expect.js new file mode 100644 index 0000000000000..8dc8af4cab894 --- /dev/null +++ b/packages/kbn-expect/expect.js @@ -0,0 +1,971 @@ +/* eslint-disable */ + +var exports = module.exports; + +/** + * Exports. + */ + +module.exports = expect; +expect.Assertion = Assertion; + +/** + * Exports version. + */ + +expect.version = '0.3.1'; + +/** + * Possible assertion flags. + */ + +var flags = { + not: ['to', 'be', 'have', 'include', 'only'] + , to: ['be', 'have', 'include', 'only', 'not'] + , only: ['have'] + , have: ['own'] + , be: ['an'] +}; + +function expect (obj) { + return new Assertion(obj); +} + +/** + * Constructor + * + * @api private + */ + +function Assertion (obj, flag, parent) { + this.obj = obj; + this.flags = {}; + + if (undefined != parent) { + this.flags[flag] = true; + + for (var i in parent.flags) { + if (parent.flags.hasOwnProperty(i)) { + this.flags[i] = true; + } + } + } + + var $flags = flag ? flags[flag] : keys(flags) + , self = this; + + if ($flags) { + for (var i = 0, l = $flags.length; i < l; i++) { + // avoid recursion + if (this.flags[$flags[i]]) continue; + + var name = $flags[i] + , assertion = new Assertion(this.obj, name, this) + + if ('function' == typeof Assertion.prototype[name]) { + // clone the function, make sure we dont touch the prot reference + var old = this[name]; + this[name] = function () { + return old.apply(self, arguments); + }; + + for (var fn in Assertion.prototype) { + if (Assertion.prototype.hasOwnProperty(fn) && fn != name) { + if (typeof this[name] === 'function' && fn === 'length') { + continue; + } + + this[name][fn] = bind(assertion[fn], assertion); + } + } + } else { + this[name] = assertion; + } + } + } +} + +/** + * Performs an assertion + * + * @api private + */ + +Assertion.prototype.assert = function (truth, msg, error, expected) { + var msg = this.flags.not ? error : msg + , ok = this.flags.not ? !truth : truth + , err; + + if (!ok) { + err = new Error(msg.call(this)); + if (arguments.length > 3) { + err.actual = this.obj; + err.expected = expected; + err.showDiff = true; + } + throw err; + } + + this.and = new Assertion(this.obj); +}; + +/** + * Check if the value is truthy + * + * @api public + */ + +Assertion.prototype.ok = function () { + this.assert( + !!this.obj + , function(){ return 'expected ' + i(this.obj) + ' to be truthy' } + , function(){ return 'expected ' + i(this.obj) + ' to be falsy' }); +}; + +/** + * Creates an anonymous function which calls fn with arguments. + * + * @api public + */ + +Assertion.prototype.withArgs = function() { + expect(this.obj).to.be.a('function'); + var fn = this.obj; + var args = Array.prototype.slice.call(arguments); + return expect(function() { fn.apply(null, args); }); +}; + +/** + * Assert that the function throws. + * + * @param {Function|RegExp} callback, or regexp to match error string against + * @api public + */ + +Assertion.prototype['throw'] = +Assertion.prototype.throwError = +Assertion.prototype.throwException = function (fn) { + expect(this.obj).to.be.a('function'); + + var thrown = false + , not = this.flags.not; + + try { + this.obj(); + } catch (e) { + if (isRegExp(fn)) { + var subject = 'string' == typeof e ? e : e.message; + if (not) { + expect(subject).to.not.match(fn); + } else { + expect(subject).to.match(fn); + } + } else if ('function' == typeof fn) { + fn(e); + } + thrown = true; + } + + if (isRegExp(fn) && not) { + // in the presence of a matcher, ensure the `not` only applies to + // the matching. + this.flags.not = false; + } + + var name = this.obj.name || 'fn'; + this.assert( + thrown + , function(){ return 'expected ' + name + ' to throw an exception' } + , function(){ return 'expected ' + name + ' not to throw an exception' }); +}; + +/** + * Checks if the array is empty. + * + * @api public + */ + +Assertion.prototype.empty = function () { + var expectation; + + if ('object' == typeof this.obj && null !== this.obj && !isArray(this.obj)) { + if ('number' == typeof this.obj.length) { + expectation = !this.obj.length; + } else { + expectation = !keys(this.obj).length; + } + } else { + if ('string' != typeof this.obj) { + expect(this.obj).to.be.an('object'); + } + + expect(this.obj).to.have.property('length'); + expectation = !this.obj.length; + } + + this.assert( + expectation + , function(){ return 'expected ' + i(this.obj) + ' to be empty' } + , function(){ return 'expected ' + i(this.obj) + ' to not be empty' }); + return this; +}; + +/** + * Checks if the obj exactly equals another. + * + * @api public + */ + +Assertion.prototype.be = +Assertion.prototype.equal = function (obj) { + this.assert( + obj === this.obj + , function(){ return 'expected ' + i(this.obj) + ' to equal ' + i(obj) } + , function(){ return 'expected ' + i(this.obj) + ' to not equal ' + i(obj) }); + return this; +}; + +/** + * Checks if the obj sortof equals another. + * + * @api public + */ + +Assertion.prototype.eql = function (obj) { + this.assert( + expect.eql(this.obj, obj) + , function(){ return 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj) } + , function(){ return 'expected ' + i(this.obj) + ' to sort of not equal ' + i(obj) } + , obj); + return this; +}; + +/** + * Assert within start to finish (inclusive). + * + * @param {Number} start + * @param {Number} finish + * @api public + */ + +Assertion.prototype.within = function (start, finish) { + var range = start + '..' + finish; + this.assert( + this.obj >= start && this.obj <= finish + , function(){ return 'expected ' + i(this.obj) + ' to be within ' + range } + , function(){ return 'expected ' + i(this.obj) + ' to not be within ' + range }); + return this; +}; + +/** + * Assert typeof / instance of + * + * @api public + */ + +Assertion.prototype.a = +Assertion.prototype.an = function (type) { + if ('string' == typeof type) { + // proper english in error msg + var n = /^[aeiou]/.test(type) ? 'n' : ''; + + // typeof with support for 'array' + this.assert( + 'array' == type ? isArray(this.obj) : + 'regexp' == type ? isRegExp(this.obj) : + 'object' == type + ? 'object' == typeof this.obj && null !== this.obj + : type == typeof this.obj + , function(){ return 'expected ' + i(this.obj) + ' to be a' + n + ' ' + type } + , function(){ return 'expected ' + i(this.obj) + ' not to be a' + n + ' ' + type }); + } else { + // instanceof + var name = type.name || 'supplied constructor'; + this.assert( + this.obj instanceof type + , function(){ return 'expected ' + i(this.obj) + ' to be an instance of ' + name } + , function(){ return 'expected ' + i(this.obj) + ' not to be an instance of ' + name }); + } + + return this; +}; + +/** + * Assert numeric value above _n_. + * + * @param {Number} n + * @api public + */ + +Assertion.prototype.greaterThan = +Assertion.prototype.above = function (n) { + this.assert( + this.obj > n + , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n } + , function(){ return 'expected ' + i(this.obj) + ' to be below ' + n }); + return this; +}; + +/** + * Assert numeric value below _n_. + * + * @param {Number} n + * @api public + */ + +Assertion.prototype.lessThan = +Assertion.prototype.below = function (n) { + this.assert( + this.obj < n + , function(){ return 'expected ' + i(this.obj) + ' to be below ' + n } + , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n }); + return this; +}; + +/** + * Assert string value matches _regexp_. + * + * @param {RegExp} regexp + * @api public + */ + +Assertion.prototype.match = function (regexp) { + this.assert( + regexp.exec(this.obj) + , function(){ return 'expected ' + i(this.obj) + ' to match ' + regexp } + , function(){ return 'expected ' + i(this.obj) + ' not to match ' + regexp }); + return this; +}; + +/** + * Assert property "length" exists and has value of _n_. + * + * @param {Number} n + * @api public + */ + +Assertion.prototype.length = function (n) { + expect(this.obj).to.have.property('length'); + var len = this.obj.length; + this.assert( + n == len + , function(){ return 'expected ' + i(this.obj) + ' to have a length of ' + n + ' but got ' + len } + , function(){ return 'expected ' + i(this.obj) + ' to not have a length of ' + len }); + return this; +}; + +/** + * Assert property _name_ exists, with optional _val_. + * + * @param {String} name + * @param {Mixed} val + * @api public + */ + +Assertion.prototype.property = function (name, val) { + if (this.flags.own) { + this.assert( + Object.prototype.hasOwnProperty.call(this.obj, name) + , function(){ return 'expected ' + i(this.obj) + ' to have own property ' + i(name) } + , function(){ return 'expected ' + i(this.obj) + ' to not have own property ' + i(name) }); + return this; + } + + if (this.flags.not && undefined !== val) { + if (undefined === this.obj[name]) { + throw new Error(i(this.obj) + ' has no property ' + i(name)); + } + } else { + var hasProp; + try { + hasProp = name in this.obj + } catch (e) { + hasProp = undefined !== this.obj[name] + } + + this.assert( + hasProp + , function(){ return 'expected ' + i(this.obj) + ' to have a property ' + i(name) } + , function(){ return 'expected ' + i(this.obj) + ' to not have a property ' + i(name) }); + } + + if (undefined !== val) { + this.assert( + val === this.obj[name] + , function(){ return 'expected ' + i(this.obj) + ' to have a property ' + i(name) + + ' of ' + i(val) + ', but got ' + i(this.obj[name]) } + , function(){ return 'expected ' + i(this.obj) + ' to not have a property ' + i(name) + + ' of ' + i(val) }); + } + + this.obj = this.obj[name]; + return this; +}; + +/** + * Assert that the array contains _obj_ or string contains _obj_. + * + * @param {Mixed} obj|string + * @api public + */ + +Assertion.prototype.string = +Assertion.prototype.contain = function (obj) { + if ('string' == typeof this.obj) { + this.assert( + ~this.obj.indexOf(obj) + , function(){ return 'expected ' + i(this.obj) + ' to contain ' + i(obj) } + , function(){ return 'expected ' + i(this.obj) + ' to not contain ' + i(obj) }); + } else { + this.assert( + ~indexOf(this.obj, obj) + , function(){ return 'expected ' + i(this.obj) + ' to contain ' + i(obj) } + , function(){ return 'expected ' + i(this.obj) + ' to not contain ' + i(obj) }); + } + return this; +}; + +/** + * Assert exact keys or inclusion of keys by using + * the `.own` modifier. + * + * @param {Array|String ...} keys + * @api public + */ + +Assertion.prototype.key = +Assertion.prototype.keys = function ($keys) { + var str + , ok = true; + + $keys = isArray($keys) + ? $keys + : Array.prototype.slice.call(arguments); + + if (!$keys.length) throw new Error('keys required'); + + var actual = keys(this.obj) + , len = $keys.length; + + // Inclusion + ok = every($keys, function (key) { + return ~indexOf(actual, key); + }); + + // Strict + if (!this.flags.not && this.flags.only) { + ok = ok && $keys.length == actual.length; + } + + // Key string + if (len > 1) { + $keys = map($keys, function (key) { + return i(key); + }); + var last = $keys.pop(); + str = $keys.join(', ') + ', and ' + last; + } else { + str = i($keys[0]); + } + + // Form + str = (len > 1 ? 'keys ' : 'key ') + str; + + // Have / include + str = (!this.flags.only ? 'include ' : 'only have ') + str; + + // Assertion + this.assert( + ok + , function(){ return 'expected ' + i(this.obj) + ' to ' + str } + , function(){ return 'expected ' + i(this.obj) + ' to not ' + str }); + + return this; +}; + +/** + * Assert a failure. + * + * @param {String ...} custom message + * @api public + */ +Assertion.prototype.fail = function (msg) { + var error = function() { return msg || "explicit failure"; } + this.assert(false, error, error); + return this; +}; + +/** + * Function bind implementation. + */ + +function bind (fn, scope) { + return function () { + return fn.apply(scope, arguments); + } +} + +/** + * Array every compatibility + * + * @see bit.ly/5Fq1N2 + * @api public + */ + +function every (arr, fn, thisObj) { + var scope = thisObj || global; + for (var i = 0, j = arr.length; i < j; ++i) { + if (!fn.call(scope, arr[i], i, arr)) { + return false; + } + } + return true; +} + +/** + * Array indexOf compatibility. + * + * @see bit.ly/a5Dxa2 + * @api public + */ + +function indexOf (arr, o, i) { + if (Array.prototype.indexOf) { + return Array.prototype.indexOf.call(arr, o, i); + } + + if (arr.length === undefined) { + return -1; + } + + for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0 + ; i < j && arr[i] !== o; i++); + + return j <= i ? -1 : i; +} + +// https://gist.github.com/1044128/ +var getOuterHTML = function(element) { + if ('outerHTML' in element) return element.outerHTML; + var ns = "http://www.w3.org/1999/xhtml"; + var container = document.createElementNS(ns, '_'); + var xmlSerializer = new XMLSerializer(); + var html; + if (document.xmlVersion) { + return xmlSerializer.serializeToString(element); + } else { + container.appendChild(element.cloneNode(false)); + html = container.innerHTML.replace('><', '>' + element.innerHTML + '<'); + container.innerHTML = ''; + return html; + } +}; + +// Returns true if object is a DOM element. +var isDOMElement = function (object) { + if (typeof HTMLElement === 'object') { + return object instanceof HTMLElement; + } else { + return object && + typeof object === 'object' && + object.nodeType === 1 && + typeof object.nodeName === 'string'; + } +}; + +/** + * Inspects an object. + * + * @see taken from node.js `util` module (copyright Joyent, MIT license) + * @api private + */ + +function i (obj, showHidden, depth) { + var seen = []; + + function stylize (str) { + return str; + } + + function format (value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (value && typeof value.inspect === 'function' && + // Filter out the util module, it's inspect function is special + value !== exports && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + return value.inspect(recurseTimes); + } + + // Primitive types cannot have properties + switch (typeof value) { + case 'undefined': + return stylize('undefined', 'undefined'); + + case 'string': + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return stylize(simple, 'string'); + + case 'number': + return stylize('' + value, 'number'); + + case 'boolean': + return stylize('' + value, 'boolean'); + } + // For some reason typeof null is "object", so special case here. + if (value === null) { + return stylize('null', 'null'); + } + + if (isDOMElement(value)) { + return getOuterHTML(value); + } + + // Look up the keys of the object. + var visible_keys = keys(value); + var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys; + + // Functions without properties can be shortcutted. + if (typeof value === 'function' && $keys.length === 0) { + if (isRegExp(value)) { + return stylize('' + value, 'regexp'); + } else { + var name = value.name ? ': ' + value.name : ''; + return stylize('[Function' + name + ']', 'special'); + } + } + + // Dates without properties can be shortcutted + if (isDate(value) && $keys.length === 0) { + return stylize(value.toUTCString(), 'date'); + } + + // Error objects can be shortcutted + if (value instanceof Error) { + return stylize("["+value.toString()+"]", 'Error'); + } + + var base, type, braces; + // Determine the object type + if (isArray(value)) { + type = 'Array'; + braces = ['[', ']']; + } else { + type = 'Object'; + braces = ['{', '}']; + } + + // Make functions say that they are functions + if (typeof value === 'function') { + var n = value.name ? ': ' + value.name : ''; + base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; + } else { + base = ''; + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + value.toUTCString(); + } + + if ($keys.length === 0) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return stylize('' + value, 'regexp'); + } else { + return stylize('[Object]', 'special'); + } + } + + seen.push(value); + + var output = map($keys, function (key) { + var name, str; + if (value.__lookupGetter__) { + if (value.__lookupGetter__(key)) { + if (value.__lookupSetter__(key)) { + str = stylize('[Getter/Setter]', 'special'); + } else { + str = stylize('[Getter]', 'special'); + } + } else { + if (value.__lookupSetter__(key)) { + str = stylize('[Setter]', 'special'); + } + } + } + if (indexOf(visible_keys, key) < 0) { + name = '[' + key + ']'; + } + if (!str) { + if (indexOf(seen, value[key]) < 0) { + if (recurseTimes === null) { + str = format(value[key]); + } else { + str = format(value[key], recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (isArray(value)) { + str = map(str.split('\n'), function (line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + map(str.split('\n'), function (line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = stylize('[Circular]', 'special'); + } + } + if (typeof name === 'undefined') { + if (type === 'Array' && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = stylize(name, 'string'); + } + } + + return name + ': ' + str; + }); + + seen.pop(); + + var numLinesEst = 0; + var length = reduce(output, function (prev, cur) { + numLinesEst++; + if (indexOf(cur, '\n') >= 0) numLinesEst++; + return prev + cur.length + 1; + }, 0); + + if (length > 50) { + output = braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + + } else { + output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; + } + + return output; + } + return format(obj, (typeof depth === 'undefined' ? 2 : depth)); +} + +expect.stringify = i; + +function isArray (ar) { + return Object.prototype.toString.call(ar) === '[object Array]'; +} + +function isRegExp(re) { + var s; + try { + s = '' + re; + } catch (e) { + return false; + } + + return re instanceof RegExp || // easy case + // duck-type for context-switching evalcx case + typeof(re) === 'function' && + re.constructor.name === 'RegExp' && + re.compile && + re.test && + re.exec && + s.match(/^\/.*\/[gim]{0,3}$/); +} + +function isDate(d) { + return d instanceof Date; +} + +function keys (obj) { + if (Object.keys) { + return Object.keys(obj); + } + + var keys = []; + + for (var i in obj) { + if (Object.prototype.hasOwnProperty.call(obj, i)) { + keys.push(i); + } + } + + return keys; +} + +function map (arr, mapper, that) { + if (Array.prototype.map) { + return Array.prototype.map.call(arr, mapper, that); + } + + var other= new Array(arr.length); + + for (var i= 0, n = arr.length; i= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + + // if array contains no values, no initial value to return + if (++i >= len) + throw new TypeError(); + } while (true); + } + + for (; i < len; i++) { + if (i in this) + rv = fun.call(null, rv, this[i], i, this); + } + + return rv; +} + +/** + * Asserts deep equality + * + * @see taken from node.js `assert` module (copyright Joyent, MIT license) + * @api private + */ + +expect.eql = function eql(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + } else if ('undefined' != typeof Buffer + && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { + if (actual.length != expected.length) return false; + + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) return false; + } + + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + // If both are regular expression use the special `regExpEquiv` method + // to determine equivalence. + } else if (isRegExp(actual) && isRegExp(expected)) { + return regExpEquiv(actual, expected); + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +}; + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function regExpEquiv (a, b) { + return a.source === b.source && a.global === b.global && + a.ignoreCase === b.ignoreCase && a.multiline === b.multiline; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return expect.eql(a, b); + } + try{ + var ka = keys(a), + kb = keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!expect.eql(a[key], b[key])) + return false; + } + return true; +} diff --git a/packages/kbn-expect/expect.js.d.ts b/packages/kbn-expect/expect.js.d.ts new file mode 100644 index 0000000000000..9e0b069499030 --- /dev/null +++ b/packages/kbn-expect/expect.js.d.ts @@ -0,0 +1,221 @@ +// tslint:disable + +// Type definitions for expect.js 0.3.1 +// Project: https://github.com/Automattic/expect.js +// Definitions by: Teppei Sato +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// License: MIT + +export default function expect(target?: any): Root; + +interface Assertion { + /** + * Assert typeof / instanceof. + */ + an: An; + /** + * Check if the value is truthy + */ + ok(): void; + + /** + * Creates an anonymous function which calls fn with arguments. + */ + withArgs(...args: any[]): Root; + + /** + * Assert that the function throws. + * + * @param fn callback to match error string against + */ + throwError(fn?: (exception: any) => void): void; + + /** + * Assert that the function throws. + * + * @param fn callback to match error string against + */ + throwException(fn?: (exception: any) => void): void; + + /** + * Assert that the function throws. + * + * @param regexp regexp to match error string against + */ + throwError(regexp: RegExp): void; + + /** + * Assert that the function throws. + * + * @param fn callback to match error string against + */ + throwException(regexp: RegExp): void; + + /** + * Checks if the array is empty. + */ + empty(): Assertion; + + /** + * Checks if the obj exactly equals another. + */ + equal(obj: any): Assertion; + + /** + * Checks if the obj sortof equals another. + */ + eql(obj: any): Assertion; + + /** + * Assert within start to finish (inclusive). + * + * @param start + * @param finish + */ + within(start: number, finish: number): Assertion; + + /** + * Assert typeof. + */ + a(type: string): Assertion; + + /** + * Assert instanceof. + */ + a(type: Function): Assertion; + + /** + * Assert numeric value above n. + */ + greaterThan(n: number): Assertion; + + /** + * Assert numeric value above n. + */ + above(n: number): Assertion; + + /** + * Assert numeric value below n. + */ + lessThan(n: number): Assertion; + + /** + * Assert numeric value below n. + */ + below(n: number): Assertion; + + /** + * Assert string value matches regexp. + * + * @param regexp + */ + match(regexp: RegExp): Assertion; + + /** + * Assert property "length" exists and has value of n. + * + * @param n + */ + length(n: number): Assertion; + + /** + * Assert property name exists, with optional val. + * + * @param name + * @param val + */ + property(name: string, val?: any): Assertion; + + /** + * Assert that string contains str. + */ + contain(str: string): Assertion; + string(str: string): Assertion; + + /** + * Assert that the array contains obj. + */ + contain(obj: any): Assertion; + string(obj: any): Assertion; + + /** + * Assert exact keys or inclusion of keys by using the `.own` modifier. + */ + key(keys: string[]): Assertion; + /** + * Assert exact keys or inclusion of keys by using the `.own` modifier. + */ + key(...keys: string[]): Assertion; + /** + * Assert exact keys or inclusion of keys by using the `.own` modifier. + */ + keys(keys: string[]): Assertion; + /** + * Assert exact keys or inclusion of keys by using the `.own` modifier. + */ + keys(...keys: string[]): Assertion; + + /** + * Assert a failure. + */ + fail(message?: string): Assertion; +} + +interface Root extends Assertion { + not: Not; + to: To; + only: Only; + have: Have; + be: Be; +} + +interface Be extends Assertion { + /** + * Checks if the obj exactly equals another. + */ + (obj: any): Assertion; + + an: An; +} + +interface An extends Assertion { + /** + * Assert typeof. + */ + (type: string): Assertion; + + /** + * Assert instanceof. + */ + (type: Function): Assertion; +} + +interface Not extends NotBase { + to: ToBase; +} + +interface NotBase extends Assertion { + be: Be; + have: Have; + include: Assertion; + only: Only; +} + +interface To extends ToBase { + not: NotBase; +} + +interface ToBase extends Assertion { + be: Be; + have: Have; + include: Assertion; + only: Only; +} + +interface Only extends Assertion { + have: Have; +} + +interface Have extends Assertion { + own: Assertion; +} diff --git a/packages/kbn-expect/package.json b/packages/kbn-expect/package.json new file mode 100644 index 0000000000000..0975f5762fa1c --- /dev/null +++ b/packages/kbn-expect/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/expect", + "main": "./expect.js", + "version": "1.0.0", + "license": "MIT", + "private": true +} diff --git a/packages/kbn-expect/tsconfig.json b/packages/kbn-expect/tsconfig.json new file mode 100644 index 0000000000000..a09ae2d7ae641 --- /dev/null +++ b/packages/kbn-expect/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "include": [ + "expect.js.d.ts" + ] +} diff --git a/packages/kbn-plugin-generator/sao_template/template/package_template.json b/packages/kbn-plugin-generator/sao_template/template/package_template.json index a3641c9c1a942..80e6ae8642e15 100644 --- a/packages/kbn-plugin-generator/sao_template/template/package_template.json +++ b/packages/kbn-plugin-generator/sao_template/template/package_template.json @@ -25,6 +25,7 @@ "devDependencies": { "@elastic/eslint-config-kibana": "link:../../kibana/packages/eslint-config-kibana", "@elastic/eslint-import-resolver-kibana": "link:../../kibana/packages/kbn-eslint-import-resolver-kibana", + "@kbn/expect": "1.0.0", "@kbn/plugin-helpers": "link:../../kibana/packages/kbn-plugin-helpers", "babel-eslint": "^9.0.0", "eslint": "^5.6.0", @@ -35,7 +36,6 @@ "eslint-plugin-mocha": "^5.2.0", "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", - "eslint-plugin-react": "^7.11.1", - "expect.js": "^0.3.1" + "eslint-plugin-react": "^7.11.1" } } diff --git a/packages/kbn-plugin-generator/sao_template/template/public/__tests__/index.js b/packages/kbn-plugin-generator/sao_template/template/public/__tests__/index.js index f1e0ae8fb6f3d..9320bd7b028a8 100755 --- a/packages/kbn-plugin-generator/sao_template/template/public/__tests__/index.js +++ b/packages/kbn-plugin-generator/sao_template/template/public/__tests__/index.js @@ -1,4 +1,4 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('suite', () => { it('is a test', () => { diff --git a/packages/kbn-plugin-generator/sao_template/template/server/__tests__/index.js b/packages/kbn-plugin-generator/sao_template/template/server/__tests__/index.js index f1e0ae8fb6f3d..9320bd7b028a8 100755 --- a/packages/kbn-plugin-generator/sao_template/template/server/__tests__/index.js +++ b/packages/kbn-plugin-generator/sao_template/template/server/__tests__/index.js @@ -1,4 +1,4 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('suite', () => { it('is a test', () => { diff --git a/packages/kbn-test-subj-selector/package.json b/packages/kbn-test-subj-selector/package.json index 83291dc059b94..f93245fd08848 100755 --- a/packages/kbn-test-subj-selector/package.json +++ b/packages/kbn-test-subj-selector/package.json @@ -10,7 +10,7 @@ "author": "Spencer Alger ", "license": "Apache-2.0", "devDependencies": { - "expect.js": "^0.3.1", + "@kbn/expect": "1.0.0", "mocha": "^2.3.4" } } diff --git a/packages/kbn-test-subj-selector/test/index.js b/packages/kbn-test-subj-selector/test/index.js index 1c0df4d3149f8..c5a3826d19479 100755 --- a/packages/kbn-test-subj-selector/test/index.js +++ b/packages/kbn-test-subj-selector/test/index.js @@ -18,7 +18,7 @@ */ const testSubjSelector = require('../'); -const expect = require('expect.js'); +const expect = require('@kbn/expect'); describe('testSubjSelector()', function() { it('converts subjectSelectors to cssSelectors', function() { diff --git a/packages/kbn-test/types/README.md b/packages/kbn-test/types/README.md index 5e4b2c6da6141..1298d2a4afc0a 100644 --- a/packages/kbn-test/types/README.md +++ b/packages/kbn-test/types/README.md @@ -2,5 +2,4 @@ Shared types used by different parts of the tests - - **`expect.js.d.ts`**: This is a fork of the expect.js types that have been slightly modified to only expose a module type for `import expect from 'expect.js'` statements. The `@types/expect.js` includes types for the `expect` global, which is useful for some uses of the library but conflicts with the jest types we use. Making the type "module only" prevents them from conflicting. - **`ftr.d.ts`**: These types are generic types for using the functional test runner. They are here because we plan to move the functional test runner into the `@kbn/test` package at some point and having them here makes them a lot easier to import from all over the place like we do. \ No newline at end of file diff --git a/packages/kbn-test/types/expect.js.d.ts b/packages/kbn-test/types/expect.js.d.ts deleted file mode 100644 index fd3cbd852f967..0000000000000 --- a/packages/kbn-test/types/expect.js.d.ts +++ /dev/null @@ -1,225 +0,0 @@ -// tslint:disable - -// Type definitions for expect.js 0.3.1 -// Project: https://github.com/Automattic/expect.js -// Definitions by: Teppei Sato -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// License: MIT - -declare module 'expect.js' { - function expect(target?: any): Root; - - interface Assertion { - /** - * Assert typeof / instanceof. - */ - an: An; - /** - * Check if the value is truthy - */ - ok(): void; - - /** - * Creates an anonymous function which calls fn with arguments. - */ - withArgs(...args: any[]): Root; - - /** - * Assert that the function throws. - * - * @param fn callback to match error string against - */ - throwError(fn?: (exception: any) => void): void; - - /** - * Assert that the function throws. - * - * @param fn callback to match error string against - */ - throwException(fn?: (exception: any) => void): void; - - /** - * Assert that the function throws. - * - * @param regexp regexp to match error string against - */ - throwError(regexp: RegExp): void; - - /** - * Assert that the function throws. - * - * @param fn callback to match error string against - */ - throwException(regexp: RegExp): void; - - /** - * Checks if the array is empty. - */ - empty(): Assertion; - - /** - * Checks if the obj exactly equals another. - */ - equal(obj: any): Assertion; - - /** - * Checks if the obj sortof equals another. - */ - eql(obj: any): Assertion; - - /** - * Assert within start to finish (inclusive). - * - * @param start - * @param finish - */ - within(start: number, finish: number): Assertion; - - /** - * Assert typeof. - */ - a(type: string): Assertion; - - /** - * Assert instanceof. - */ - a(type: Function): Assertion; - - /** - * Assert numeric value above n. - */ - greaterThan(n: number): Assertion; - - /** - * Assert numeric value above n. - */ - above(n: number): Assertion; - - /** - * Assert numeric value below n. - */ - lessThan(n: number): Assertion; - - /** - * Assert numeric value below n. - */ - below(n: number): Assertion; - - /** - * Assert string value matches regexp. - * - * @param regexp - */ - match(regexp: RegExp): Assertion; - - /** - * Assert property "length" exists and has value of n. - * - * @param n - */ - length(n: number): Assertion; - - /** - * Assert property name exists, with optional val. - * - * @param name - * @param val - */ - property(name: string, val?: any): Assertion; - - /** - * Assert that string contains str. - */ - contain(str: string): Assertion; - string(str: string): Assertion; - - /** - * Assert that the array contains obj. - */ - contain(obj: any): Assertion; - string(obj: any): Assertion; - - /** - * Assert exact keys or inclusion of keys by using the `.own` modifier. - */ - key(keys: string[]): Assertion; - /** - * Assert exact keys or inclusion of keys by using the `.own` modifier. - */ - key(...keys: string[]): Assertion; - /** - * Assert exact keys or inclusion of keys by using the `.own` modifier. - */ - keys(keys: string[]): Assertion; - /** - * Assert exact keys or inclusion of keys by using the `.own` modifier. - */ - keys(...keys: string[]): Assertion; - - /** - * Assert a failure. - */ - fail(message?: string): Assertion; - } - - interface Root extends Assertion { - not: Not; - to: To; - only: Only; - have: Have; - be: Be; - } - - interface Be extends Assertion { - /** - * Checks if the obj exactly equals another. - */ - (obj: any): Assertion; - - an: An; - } - - interface An extends Assertion { - /** - * Assert typeof. - */ - (type: string): Assertion; - - /** - * Assert instanceof. - */ - (type: Function): Assertion; - } - - interface Not extends NotBase { - to: ToBase; - } - - interface NotBase extends Assertion { - be: Be; - have: Have; - include: Assertion; - only: Only; - } - - interface To extends ToBase { - not: NotBase; - } - - interface ToBase extends Assertion { - be: Be; - have: Have; - include: Assertion; - only: Only; - } - - interface Only extends Assertion { - have: Have; - } - - interface Have extends Assertion { - own: Assertion; - } - - export default expect; -} diff --git a/src/dev/__tests__/file.js b/src/dev/__tests__/file.js index 36fe23a81bab9..0e8790f32c7c9 100644 --- a/src/dev/__tests__/file.js +++ b/src/dev/__tests__/file.js @@ -19,7 +19,7 @@ import { resolve, sep } from 'path'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { File } from '../file'; diff --git a/src/dev/__tests__/node_versions_must_match.js b/src/dev/__tests__/node_versions_must_match.js index e01d93f512844..99f2e255f47ea 100644 --- a/src/dev/__tests__/node_versions_must_match.js +++ b/src/dev/__tests__/node_versions_must_match.js @@ -21,7 +21,7 @@ import fs from 'fs'; import { engines } from '../../../package.json'; import { promisify } from 'util'; const readFile = promisify(fs.readFile); -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('All configs should use a single version of Node', () => { it('should compare .node-version and .nvmrc', async () => { diff --git a/src/dev/build/lib/__tests__/build.js b/src/dev/build/lib/__tests__/build.js index 466abd67f0cd3..28a96c2108436 100644 --- a/src/dev/build/lib/__tests__/build.js +++ b/src/dev/build/lib/__tests__/build.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { createBuild } from '../build'; diff --git a/src/dev/build/lib/__tests__/config.js b/src/dev/build/lib/__tests__/config.js index 6b395ce137e63..2bb0f349715af 100644 --- a/src/dev/build/lib/__tests__/config.js +++ b/src/dev/build/lib/__tests__/config.js @@ -19,7 +19,7 @@ import { resolve } from 'path'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import pkg from '../../../../../package.json'; import { getConfig } from '../config'; diff --git a/src/dev/build/lib/__tests__/errors.js b/src/dev/build/lib/__tests__/errors.js index 7edc6244f8fe4..dc23b3e372bc6 100644 --- a/src/dev/build/lib/__tests__/errors.js +++ b/src/dev/build/lib/__tests__/errors.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isErrorLogged, markErrorLogged } from '../errors'; diff --git a/src/dev/build/lib/__tests__/fs.js b/src/dev/build/lib/__tests__/fs.js index 3c0c515342039..a4e2a5f444751 100644 --- a/src/dev/build/lib/__tests__/fs.js +++ b/src/dev/build/lib/__tests__/fs.js @@ -21,7 +21,7 @@ import { resolve } from 'path'; import { chmodSync, statSync } from 'fs'; import del from 'del'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { mkdirp, write, read, getChildPaths, copy, copyAll, getFileHash, untar } from '../fs'; diff --git a/src/dev/build/lib/__tests__/platform.js b/src/dev/build/lib/__tests__/platform.js index 91aef80d0e836..86ef1749feca9 100644 --- a/src/dev/build/lib/__tests__/platform.js +++ b/src/dev/build/lib/__tests__/platform.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createPlatform } from '../platform'; diff --git a/src/dev/build/lib/__tests__/runner.js b/src/dev/build/lib/__tests__/runner.js index c41d1fb6a8d2b..07d484f72f185 100644 --- a/src/dev/build/lib/__tests__/runner.js +++ b/src/dev/build/lib/__tests__/runner.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ToolingLog } from '@kbn/dev-utils'; import { createRunner } from '../runner'; diff --git a/src/dev/build/lib/__tests__/version_info.js b/src/dev/build/lib/__tests__/version_info.js index 1ec4eb5c51747..517a6cc494cf8 100644 --- a/src/dev/build/lib/__tests__/version_info.js +++ b/src/dev/build/lib/__tests__/version_info.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import pkg from '../../../../../package.json'; import { getVersionInfo } from '../version_info'; diff --git a/src/dev/build/tasks/nodejs/__tests__/download.js b/src/dev/build/tasks/nodejs/__tests__/download.js index a3514d3254cce..0007e9ae9df5a 100644 --- a/src/dev/build/tasks/nodejs/__tests__/download.js +++ b/src/dev/build/tasks/nodejs/__tests__/download.js @@ -23,7 +23,7 @@ import { readFileSync } from 'fs'; import del from 'del'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Wreck from 'wreck'; import { ToolingLog } from '@kbn/dev-utils'; diff --git a/src/dev/build/tasks/nodejs/__tests__/download_node_builds_task.js b/src/dev/build/tasks/nodejs/__tests__/download_node_builds_task.js index 191ca47e12563..0206680b4d9fe 100644 --- a/src/dev/build/tasks/nodejs/__tests__/download_node_builds_task.js +++ b/src/dev/build/tasks/nodejs/__tests__/download_node_builds_task.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as NodeShasumsNS from '../node_shasums'; import * as NodeDownloadInfoNS from '../node_download_info'; diff --git a/src/dev/build/tasks/nodejs/__tests__/node_shasums.js b/src/dev/build/tasks/nodejs/__tests__/node_shasums.js index 61fd8f6400560..3e400283dbd80 100644 --- a/src/dev/build/tasks/nodejs/__tests__/node_shasums.js +++ b/src/dev/build/tasks/nodejs/__tests__/node_shasums.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getNodeShasums } from '../node_shasums'; diff --git a/src/dev/build/tasks/nodejs/__tests__/verify_existing_node_builds_task.js b/src/dev/build/tasks/nodejs/__tests__/verify_existing_node_builds_task.js index 3cf75216d286f..fa6ae4675229b 100644 --- a/src/dev/build/tasks/nodejs/__tests__/verify_existing_node_builds_task.js +++ b/src/dev/build/tasks/nodejs/__tests__/verify_existing_node_builds_task.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as NodeShasumsNS from '../node_shasums'; import * as NodeDownloadInfoNS from '../node_download_info'; diff --git a/src/dev/license_checker/__tests__/valid.js b/src/dev/license_checker/__tests__/valid.js index bb608e33d52a0..04c9347bc74ec 100644 --- a/src/dev/license_checker/__tests__/valid.js +++ b/src/dev/license_checker/__tests__/valid.js @@ -19,7 +19,7 @@ import { resolve } from 'path'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { assertLicensesValid } from '../valid'; diff --git a/src/dev/mocha/__tests__/junit_report_generation.js b/src/dev/mocha/__tests__/junit_report_generation.js index 7142a14b662e5..f7631e972ad14 100644 --- a/src/dev/mocha/__tests__/junit_report_generation.js +++ b/src/dev/mocha/__tests__/junit_report_generation.js @@ -24,7 +24,7 @@ import { fromNode as fcb } from 'bluebird'; import { parseString } from 'xml2js'; import del from 'del'; import Mocha from 'mocha'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { setupJUnitReportGeneration } from '../junit_report_generation'; diff --git a/src/dev/npm/__tests__/installed_packages.js b/src/dev/npm/__tests__/installed_packages.js index 70ccf1916c75b..24bad227cbbde 100644 --- a/src/dev/npm/__tests__/installed_packages.js +++ b/src/dev/npm/__tests__/installed_packages.js @@ -20,7 +20,7 @@ import { resolve, sep } from 'path'; import { uniq } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getInstalledPackages } from '../installed_packages'; diff --git a/src/dev/tslint/rules/moduleMigrationRule.js b/src/dev/tslint/rules/moduleMigrationRule.js new file mode 100644 index 0000000000000..be79664e889c7 --- /dev/null +++ b/src/dev/tslint/rules/moduleMigrationRule.js @@ -0,0 +1,59 @@ +/* + * 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. + */ + +const Lint = require('tslint'); + +class ModuleMigrationWalker extends Lint.RuleWalker { + visitImportDeclaration(node) { + + const moduleId = node.moduleSpecifier.text; + const mapping = this.options.find( + mapping => mapping.from === moduleId || mapping.from.startsWith(moduleId + '/') + ); + + if (!mapping) { + return; + } + + const newSource = moduleId.replace(mapping.from, mapping.to); + const start = node.moduleSpecifier.getStart(); + const width = node.moduleSpecifier.getWidth(); + + this.addFailure( + this.createFailure( + start, + width, + `Imported module "${moduleId}" should be "${newSource}"`, + this.createReplacement( + start, + width, + `'${newSource}'` + ) + ) + ); + + super.visitImportDeclaration(node); + } +} + +exports.Rule = class extends Lint.Rules.AbstractRule { + apply(sourceFile) { + return this.applyWithWalker(new ModuleMigrationWalker(sourceFile, this.getOptions())); + } +}; diff --git a/src/es_archiver/lib/__tests__/stats.js b/src/es_archiver/lib/__tests__/stats.js index eb7d9f09f858d..38febda53dbed 100644 --- a/src/es_archiver/lib/__tests__/stats.js +++ b/src/es_archiver/lib/__tests__/stats.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { uniq } from 'lodash'; import sinon from 'sinon'; diff --git a/src/es_archiver/lib/archives/__tests__/format.js b/src/es_archiver/lib/archives/__tests__/format.js index 53da1718c8926..d537245c44fc6 100644 --- a/src/es_archiver/lib/archives/__tests__/format.js +++ b/src/es_archiver/lib/archives/__tests__/format.js @@ -20,7 +20,7 @@ import Stream from 'stream'; import { createGunzip } from 'zlib'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createListStream, diff --git a/src/es_archiver/lib/archives/__tests__/parse.js b/src/es_archiver/lib/archives/__tests__/parse.js index 6645df47fc60c..2a525e76d98e8 100644 --- a/src/es_archiver/lib/archives/__tests__/parse.js +++ b/src/es_archiver/lib/archives/__tests__/parse.js @@ -20,7 +20,7 @@ import Stream, { PassThrough, Transform } from 'stream'; import { createGzip } from 'zlib'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createConcatStream, diff --git a/src/es_archiver/lib/docs/__tests__/generate_doc_records_stream.js b/src/es_archiver/lib/docs/__tests__/generate_doc_records_stream.js index d9eb99d39f87d..b4f221ea0432a 100644 --- a/src/es_archiver/lib/docs/__tests__/generate_doc_records_stream.js +++ b/src/es_archiver/lib/docs/__tests__/generate_doc_records_stream.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { delay } from 'bluebird'; import { diff --git a/src/es_archiver/lib/docs/__tests__/index_doc_records_stream.js b/src/es_archiver/lib/docs/__tests__/index_doc_records_stream.js index cdb2925e0eeaf..a0ab1430417f1 100644 --- a/src/es_archiver/lib/docs/__tests__/index_doc_records_stream.js +++ b/src/es_archiver/lib/docs/__tests__/index_doc_records_stream.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { delay } from 'bluebird'; import { diff --git a/src/es_archiver/lib/indices/__tests__/create_index_stream.js b/src/es_archiver/lib/indices/__tests__/create_index_stream.js index e705b0065427c..830512f3476ed 100644 --- a/src/es_archiver/lib/indices/__tests__/create_index_stream.js +++ b/src/es_archiver/lib/indices/__tests__/create_index_stream.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import Chance from 'chance'; diff --git a/src/es_archiver/lib/indices/__tests__/generate_index_records_stream.js b/src/es_archiver/lib/indices/__tests__/generate_index_records_stream.js index 115e7a97f0647..3ff30c0267da3 100644 --- a/src/es_archiver/lib/indices/__tests__/generate_index_records_stream.js +++ b/src/es_archiver/lib/indices/__tests__/generate_index_records_stream.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createListStream, diff --git a/src/es_archiver/lib/records/__tests__/filter_records_stream.js b/src/es_archiver/lib/records/__tests__/filter_records_stream.js index 90a89424cfa78..48a8aaf7de721 100644 --- a/src/es_archiver/lib/records/__tests__/filter_records_stream.js +++ b/src/es_archiver/lib/records/__tests__/filter_records_stream.js @@ -18,7 +18,7 @@ */ import Chance from 'chance'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createListStream, diff --git a/src/functional_test_runner/__tests__/fixtures/simple_project/tests.js b/src/functional_test_runner/__tests__/fixtures/simple_project/tests.js index 6ea7c84167229..02e49fefc587e 100644 --- a/src/functional_test_runner/__tests__/fixtures/simple_project/tests.js +++ b/src/functional_test_runner/__tests__/fixtures/simple_project/tests.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default () => { describe('app one', () => { diff --git a/src/functional_test_runner/__tests__/integration/basic.js b/src/functional_test_runner/__tests__/integration/basic.js index b5e4f5f24fd4c..1c3858a8cfd6d 100644 --- a/src/functional_test_runner/__tests__/integration/basic.js +++ b/src/functional_test_runner/__tests__/integration/basic.js @@ -20,7 +20,7 @@ import { spawnSync } from 'child_process'; import { resolve } from 'path'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const SCRIPT = resolve(__dirname, '../../../../scripts/functional_test_runner.js'); const BASIC_CONFIG = resolve(__dirname, '../fixtures/simple_project/config.js'); diff --git a/src/functional_test_runner/__tests__/integration/failure_hooks.js b/src/functional_test_runner/__tests__/integration/failure_hooks.js index 1e2c2035df889..0c00e2771bb1f 100644 --- a/src/functional_test_runner/__tests__/integration/failure_hooks.js +++ b/src/functional_test_runner/__tests__/integration/failure_hooks.js @@ -21,7 +21,7 @@ import { spawnSync } from 'child_process'; import { resolve } from 'path'; import stripAnsi from 'strip-ansi'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const SCRIPT = resolve(__dirname, '../../../../scripts/functional_test_runner.js'); const FAILURE_HOOKS_CONFIG = resolve(__dirname, '../fixtures/failure_hooks/config.js'); diff --git a/src/functional_test_runner/lib/config/__tests__/read_config_file.js b/src/functional_test_runner/lib/config/__tests__/read_config_file.js index d9da00d9b3c81..d4a08333e8143 100644 --- a/src/functional_test_runner/lib/config/__tests__/read_config_file.js +++ b/src/functional_test_runner/lib/config/__tests__/read_config_file.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ToolingLog } from '@kbn/dev-utils'; import { readConfigFile } from '../read_config_file'; diff --git a/src/legacy/core_plugins/console/__tests__/index.js b/src/legacy/core_plugins/console/__tests__/index.js index aebb5e16bc6d2..e516898ef2fd8 100644 --- a/src/legacy/core_plugins/console/__tests__/index.js +++ b/src/legacy/core_plugins/console/__tests__/index.js @@ -18,7 +18,7 @@ */ import { Deprecations } from '../../../deprecation'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import index from '../index'; import { noop } from 'lodash'; import sinon from 'sinon'; diff --git a/src/legacy/core_plugins/console/public/src/__tests__/utils.js b/src/legacy/core_plugins/console/public/src/__tests__/utils.js index 5863923c82718..fa88e42fa557f 100644 --- a/src/legacy/core_plugins/console/public/src/__tests__/utils.js +++ b/src/legacy/core_plugins/console/public/src/__tests__/utils.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import utils from '../utils'; diff --git a/src/legacy/core_plugins/console/server/__tests__/elasticsearch_proxy_config.js b/src/legacy/core_plugins/console/server/__tests__/elasticsearch_proxy_config.js index 5d00e497ec2e6..45d8346936632 100644 --- a/src/legacy/core_plugins/console/server/__tests__/elasticsearch_proxy_config.js +++ b/src/legacy/core_plugins/console/server/__tests__/elasticsearch_proxy_config.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import fs from 'fs'; import { promisify } from 'bluebird'; diff --git a/src/legacy/core_plugins/console/server/__tests__/proxy_config.js b/src/legacy/core_plugins/console/server/__tests__/proxy_config.js index 79fbf444d07f1..dd6d9c4de7602 100644 --- a/src/legacy/core_plugins/console/server/__tests__/proxy_config.js +++ b/src/legacy/core_plugins/console/server/__tests__/proxy_config.js @@ -19,7 +19,7 @@ /* eslint-env mocha */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import fs from 'fs'; import https, { Agent as HttpsAgent } from 'https'; diff --git a/src/legacy/core_plugins/console/server/__tests__/proxy_config_collection.js b/src/legacy/core_plugins/console/server/__tests__/proxy_config_collection.js index 6b9878f06952e..91797f897d8ba 100644 --- a/src/legacy/core_plugins/console/server/__tests__/proxy_config_collection.js +++ b/src/legacy/core_plugins/console/server/__tests__/proxy_config_collection.js @@ -19,7 +19,7 @@ /* eslint-env mocha */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import fs from 'fs'; import { Agent as HttpsAgent } from 'https'; diff --git a/src/legacy/core_plugins/console/server/__tests__/proxy_route/body.js b/src/legacy/core_plugins/console/server/__tests__/proxy_route/body.js index 9dae2ec8047ff..5a8bcd9ef4144 100644 --- a/src/legacy/core_plugins/console/server/__tests__/proxy_route/body.js +++ b/src/legacy/core_plugins/console/server/__tests__/proxy_route/body.js @@ -19,7 +19,7 @@ import sinon from 'sinon'; import Wreck from 'wreck'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Server } from 'hapi'; import { createProxyRoute } from '../../'; diff --git a/src/legacy/core_plugins/console/server/__tests__/proxy_route/headers.js b/src/legacy/core_plugins/console/server/__tests__/proxy_route/headers.js index 2d3ddf11e020f..a7fbd57c16d6e 100644 --- a/src/legacy/core_plugins/console/server/__tests__/proxy_route/headers.js +++ b/src/legacy/core_plugins/console/server/__tests__/proxy_route/headers.js @@ -21,7 +21,7 @@ import { request } from 'http'; import sinon from 'sinon'; import Wreck from 'wreck'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Server } from 'hapi'; import { createProxyRoute } from '../../'; diff --git a/src/legacy/core_plugins/console/server/__tests__/proxy_route/params.js b/src/legacy/core_plugins/console/server/__tests__/proxy_route/params.js index 4ceccc8855d6a..c85b30ed7f6fe 100644 --- a/src/legacy/core_plugins/console/server/__tests__/proxy_route/params.js +++ b/src/legacy/core_plugins/console/server/__tests__/proxy_route/params.js @@ -21,7 +21,7 @@ import { Agent } from 'http'; import sinon from 'sinon'; import Wreck from 'wreck'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Server } from 'hapi'; import { createProxyRoute } from '../../'; diff --git a/src/legacy/core_plugins/console/server/__tests__/proxy_route/query_string.js b/src/legacy/core_plugins/console/server/__tests__/proxy_route/query_string.js index c5b44cf39713d..8c3fc145181e3 100644 --- a/src/legacy/core_plugins/console/server/__tests__/proxy_route/query_string.js +++ b/src/legacy/core_plugins/console/server/__tests__/proxy_route/query_string.js @@ -19,7 +19,7 @@ import sinon from 'sinon'; import Wreck from 'wreck'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Server } from 'hapi'; import { createProxyRoute } from '../../'; diff --git a/src/legacy/core_plugins/console/server/__tests__/set_headers.js b/src/legacy/core_plugins/console/server/__tests__/set_headers.js index 0bbfe8d443cf9..a270cca1e586e 100644 --- a/src/legacy/core_plugins/console/server/__tests__/set_headers.js +++ b/src/legacy/core_plugins/console/server/__tests__/set_headers.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { setHeaders } from '../set_headers'; describe('#set_headers', function () { diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js b/src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js index 24df2f9c5f893..c82e4418f4d85 100644 --- a/src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js +++ b/src/legacy/core_plugins/elasticsearch/lib/__tests__/ensure_es_version.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import Promise from 'bluebird'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { esTestConfig } from '@kbn/test'; import { ensureEsVersion } from '../ensure_es_version'; diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js b/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js index 0c588b98e9a70..cae3734eca0de 100644 --- a/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js +++ b/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js @@ -19,7 +19,7 @@ import Promise from 'bluebird'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const NoConnections = require('elasticsearch').errors.NoConnections; diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/is_es_compatible_with_kibana.js b/src/legacy/core_plugins/elasticsearch/lib/__tests__/is_es_compatible_with_kibana.js index 5b7cfd372b191..092c0ecf1071c 100644 --- a/src/legacy/core_plugins/elasticsearch/lib/__tests__/is_es_compatible_with_kibana.js +++ b/src/legacy/core_plugins/elasticsearch/lib/__tests__/is_es_compatible_with_kibana.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import isEsCompatibleWithKibana from '../is_es_compatible_with_kibana'; diff --git a/src/legacy/core_plugins/input_control_vis/public/control/control.test.js b/src/legacy/core_plugins/input_control_vis/public/control/control.test.js index 366a662e989e5..9fdd79df507a4 100644 --- a/src/legacy/core_plugins/input_control_vis/public/control/control.test.js +++ b/src/legacy/core_plugins/input_control_vis/public/control/control.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Control } from './control'; function createControlParams(id, label) { diff --git a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/filter_manager.test.js b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/filter_manager.test.js index 49ac5d6700330..61d07e8fd179b 100644 --- a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/filter_manager.test.js +++ b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/filter_manager.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { FilterManager } from './filter_manager'; describe('FilterManager', function () { diff --git a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.test.js b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.test.js index 76519e0f58edc..28bebb59c4fed 100644 --- a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.test.js +++ b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PhraseFilterManager } from './phrase_filter_manager'; describe('PhraseFilterManager', function () { diff --git a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.test.js b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.test.js index be700ad72ab42..b7f88f495d578 100644 --- a/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.test.js +++ b/src/legacy/core_plugins/input_control_vis/public/control/filter_manager/range_filter_manager.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { RangeFilterManager } from './range_filter_manager'; describe('RangeFilterManager', function () { diff --git a/src/legacy/core_plugins/input_control_vis/public/lineage/lineage_map.test.js b/src/legacy/core_plugins/input_control_vis/public/lineage/lineage_map.test.js index b001899144b54..0031503fc025d 100644 --- a/src/legacy/core_plugins/input_control_vis/public/lineage/lineage_map.test.js +++ b/src/legacy/core_plugins/input_control_vis/public/lineage/lineage_map.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLineageMap } from './lineage_map'; import { CONTROL_TYPES, diff --git a/src/legacy/core_plugins/input_control_vis/public/lineage/parent_candidates.test.js b/src/legacy/core_plugins/input_control_vis/public/lineage/parent_candidates.test.js index 8ffe819ca5942..50dea30541a9d 100644 --- a/src/legacy/core_plugins/input_control_vis/public/lineage/parent_candidates.test.js +++ b/src/legacy/core_plugins/input_control_vis/public/lineage/parent_candidates.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLineageMap } from './lineage_map'; import { getParentCandidates } from './parent_candidates'; import { diff --git a/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.js b/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.js index 948ec7369d631..a6e0e13049e1c 100644 --- a/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.js +++ b/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createHandlers } from '../create_handlers'; const mockRequest = { diff --git a/src/legacy/core_plugins/kbn_doc_views/public/__tests__/doc_views.js b/src/legacy/core_plugins/kbn_doc_views/public/__tests__/doc_views.js index e14974c09838f..4bd41bfa3968e 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/__tests__/doc_views.js +++ b/src/legacy/core_plugins/kbn_doc_views/public/__tests__/doc_views.js @@ -20,7 +20,7 @@ import angular from 'angular'; import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import 'ui/render_directive'; import '../views/table'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/editors/__tests__/point_series.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/editors/__tests__/point_series.js index be20e8952492e..0a9c304777d21 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/editors/__tests__/point_series.js +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/editors/__tests__/point_series.js @@ -19,7 +19,7 @@ import angular from 'angular'; import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import $ from 'jquery'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/boolean.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/boolean.js index a96409bbce44e..e81381462386c 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/boolean.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/boolean.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createBoolFormat } from '../boolean'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/bytes.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/bytes.js index f0ece59128e04..58e69c468d503 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/bytes.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/bytes.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createBytesFormat } from '../bytes'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/color.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/color.js index e00c4c9cb455c..52b00c303445d 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/color.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/color.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createColorFormat } from '../color'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/date.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/date.js index 45748d0860456..bab2358d3c182 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/date.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/date.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment-timezone'; import { createDateFormat } from '../date'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/duration.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/duration.js index 620668fa94161..1c2fcae2e9de0 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/duration.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/duration.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createDurationFormat } from '../duration'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/ip.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/ip.js index ff3af3b2e3018..3223c45411c31 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/ip.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/ip.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createIpFormat } from '../ip'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/number.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/number.js index 100f035ac7d44..e6f72946e4267 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/number.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/number.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createNumberFormat } from '../number'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/percent.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/percent.js index ad2ba502d6052..0b0aecc8f87a0 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/percent.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/percent.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createPercentFormat } from '../percent'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/relative_date.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/relative_date.js index 551da872c77ff..7cde856542488 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/relative_date.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/relative_date.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment-timezone'; import { createRelativeDateFormat } from '../relative_date'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/string.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/string.js index 74fb0e1f886b6..04c0b9a045d38 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/string.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/string.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createStringFormat } from '../string'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/truncate.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/truncate.js index ca52dfd01000c..ed0f1bb5fdb06 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/truncate.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/truncate.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createTruncateFormat } from '../truncate'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/url.js b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/url.js index 45fc4ed3dae12..16895d9e25a8d 100644 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/url.js +++ b/src/legacy/core_plugins/kibana/common/field_formats/types/__tests__/url.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createUrlFormat } from '../url'; import { FieldFormat } from '../../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/common/highlight/__tests__/highlight_html.js b/src/legacy/core_plugins/kibana/common/highlight/__tests__/highlight_html.js index 58daae53cf78f..0fdec31ec0d00 100644 --- a/src/legacy/core_plugins/kibana/common/highlight/__tests__/highlight_html.js +++ b/src/legacy/core_plugins/kibana/common/highlight/__tests__/highlight_html.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { highlightTags } from '../highlight_tags'; import { htmlTags } from '../html_tags'; import { getHighlightHtml } from '../highlight_html'; diff --git a/src/legacy/core_plugins/kibana/common/highlight/__tests__/highlight_request.js b/src/legacy/core_plugins/kibana/common/highlight/__tests__/highlight_request.js index af81979a54774..f7015ee333f6c 100644 --- a/src/legacy/core_plugins/kibana/common/highlight/__tests__/highlight_request.js +++ b/src/legacy/core_plugins/kibana/common/highlight/__tests__/highlight_request.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getHighlightRequest } from '../highlight_request'; describe('getHighlightRequest', () => { diff --git a/src/legacy/core_plugins/kibana/common/lib/__tests__/convert_pattern_and_ingest_name.js b/src/legacy/core_plugins/kibana/common/lib/__tests__/convert_pattern_and_ingest_name.js index 65a3a94935332..d130aa1809507 100644 --- a/src/legacy/core_plugins/kibana/common/lib/__tests__/convert_pattern_and_ingest_name.js +++ b/src/legacy/core_plugins/kibana/common/lib/__tests__/convert_pattern_and_ingest_name.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { patternToIngest, ingestToPattern } from '../convert_pattern_and_ingest_name'; describe('convertPatternAndTemplateName', function () { diff --git a/src/legacy/core_plugins/kibana/common/utils/__tests__/as_pretty_string.js b/src/legacy/core_plugins/kibana/common/utils/__tests__/as_pretty_string.js index 72a41b3a3f856..723b3ccf0c596 100644 --- a/src/legacy/core_plugins/kibana/common/utils/__tests__/as_pretty_string.js +++ b/src/legacy/core_plugins/kibana/common/utils/__tests__/as_pretty_string.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { asPrettyString } from '../as_pretty_string'; describe('asPrettyString', () => { diff --git a/src/legacy/core_plugins/kibana/common/utils/__tests__/shorten_dotted_string.js b/src/legacy/core_plugins/kibana/common/utils/__tests__/shorten_dotted_string.js index e2915fcc12499..e47c08800d8e6 100644 --- a/src/legacy/core_plugins/kibana/common/utils/__tests__/shorten_dotted_string.js +++ b/src/legacy/core_plugins/kibana/common/utils/__tests__/shorten_dotted_string.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { shortenDottedString } from '../shorten_dotted_string'; describe('shortenDottedString', () => { diff --git a/src/legacy/core_plugins/kibana/public/context/api/__tests__/anchor.js b/src/legacy/core_plugins/kibana/public/context/api/__tests__/anchor.js index 598cebf4c546b..9af9d8032fb27 100644 --- a/src/legacy/core_plugins/kibana/public/context/api/__tests__/anchor.js +++ b/src/legacy/core_plugins/kibana/public/context/api/__tests__/anchor.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; diff --git a/src/legacy/core_plugins/kibana/public/context/api/__tests__/predecessors.js b/src/legacy/core_plugins/kibana/public/context/api/__tests__/predecessors.js index 698053eb93b67..63bd9987bc7e6 100644 --- a/src/legacy/core_plugins/kibana/public/context/api/__tests__/predecessors.js +++ b/src/legacy/core_plugins/kibana/public/context/api/__tests__/predecessors.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import moment from 'moment'; import * as _ from 'lodash'; diff --git a/src/legacy/core_plugins/kibana/public/context/api/__tests__/successors.js b/src/legacy/core_plugins/kibana/public/context/api/__tests__/successors.js index 14330a4d38775..ba6b0071865bc 100644 --- a/src/legacy/core_plugins/kibana/public/context/api/__tests__/successors.js +++ b/src/legacy/core_plugins/kibana/public/context/api/__tests__/successors.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import moment from 'moment'; import * as _ from 'lodash'; diff --git a/src/legacy/core_plugins/kibana/public/context/api/utils/__tests__/sorting.js b/src/legacy/core_plugins/kibana/public/context/api/utils/__tests__/sorting.js index bf221c6711d1b..bfea37088c875 100644 --- a/src/legacy/core_plugins/kibana/public/context/api/utils/__tests__/sorting.js +++ b/src/legacy/core_plugins/kibana/public/context/api/utils/__tests__/sorting.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { reverseSortDirection, diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_add_filter.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_add_filter.js index bfa0206fa7645..e616fab9c0c2f 100644 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_add_filter.js +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_add_filter.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_predecessor_count.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_predecessor_count.js index a89279e4d2cec..156264cd98563 100644 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_predecessor_count.js +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_predecessor_count.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterManagerProvider } from 'ui/filter_manager'; diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_successor_count.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_successor_count.js index ec8799473f595..f4eb82d217c98 100644 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_successor_count.js +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_successor_count.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterManagerProvider } from 'ui/filter_manager'; diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_predecessor_count.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_predecessor_count.js index d542adedcc4ce..0aa1f640f266d 100644 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_predecessor_count.js +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_predecessor_count.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterManagerProvider } from 'ui/filter_manager'; diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_query_parameters.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_query_parameters.js index fb04b5414c7b8..6a3638bc9f554 100644 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_query_parameters.js +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_query_parameters.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterManagerProvider } from 'ui/filter_manager'; diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_successor_count.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_successor_count.js index 93a388a6d6639..f4e85eefe1e6f 100644 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_successor_count.js +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_successor_count.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterManagerProvider } from 'ui/filter_manager'; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/saved_dashboards.js b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/saved_dashboards.js index 9656232031ea7..d5732a5a6cc4e 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/saved_dashboards.js +++ b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/saved_dashboards.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('SavedDashboards Service', function () { let savedDashboardLoader; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/panel/__tests__/panel_state.ts b/src/legacy/core_plugins/kibana/public/dashboard/panel/__tests__/panel_state.ts index e6162184145eb..4d910feaa4119 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/panel/__tests__/panel_state.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/panel/__tests__/panel_state.ts @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PanelState } from '../../selectors'; import { createPanelState } from '../panel_state'; diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js b/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js index 6e0e07104fa80..bf69fa09823f2 100644 --- a/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js +++ b/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import chrome from 'ui/chrome'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js index 211773a5ae867..50e9067b48367 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js @@ -22,7 +22,7 @@ import angular from 'angular'; import _ from 'lodash'; import sinon from 'sinon'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import 'ui/private'; import '../../components/field_chooser/discover_field'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js index 46c77e26c0ac5..cce6127ed9c47 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js @@ -21,7 +21,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; import { fieldCalculator } from '../../components/field_chooser/lib/field_calculator'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import 'ui/private'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js index 6920c058e1eac..f76a0ab72b212 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js @@ -21,7 +21,7 @@ import angular from 'angular'; import ngMock from 'ng_mock'; import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import $ from 'jquery'; import 'ui/private'; import '../../components/field_chooser/field_chooser'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js index c73cd2b56f752..3c7e1e83688dc 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import PluginsKibanaDiscoverHitSortFnProvider from '../_hit_sort_fn'; describe('hit sort function', function () { diff --git a/src/legacy/core_plugins/kibana/public/doc/__tests__/doc.js b/src/legacy/core_plugins/kibana/public/doc/__tests__/doc.js index a529650ae96a4..69ca21b2cf869 100644 --- a/src/legacy/core_plugins/kibana/public/doc/__tests__/doc.js +++ b/src/legacy/core_plugins/kibana/public/doc/__tests__/doc.js @@ -19,7 +19,7 @@ // Load the kibana app dependencies. import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import '..'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { timefilter } from 'ui/timefilter'; diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_boolean.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_boolean.js index b02c87b1c111d..24c67c0dccbf3 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_boolean.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_boolean.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { fieldFormats } from 'ui/registry/field_formats'; describe('Boolean Format', function () { diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_color.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_color.js index bebe202bf82d5..329624269ae1d 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_color.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_color.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { fieldFormats } from 'ui/registry/field_formats'; describe('Color Format', function () { diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js index d23b60cad87c8..e84d5e217cf7c 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import chrome from 'ui/chrome'; import { fieldFormats } from 'ui/registry/field_formats'; import { FieldFormat } from '../../../../../ui/field_formats/field_format'; diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_date.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_date.js index ac49c93f63cb5..33b3a4d4c73cf 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_date.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_date.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import moment from 'moment-timezone'; import { fieldFormats } from 'ui/registry/field_formats'; diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_duration.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_duration.js index d12c616bec6e2..baa45caa4bcc3 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_duration.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_duration.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { fieldFormats } from 'ui/registry/field_formats'; describe('Duration Format', function () { diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_ip.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_ip.js index a7b920f9eda1f..529bcf772a488 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_ip.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_ip.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { fieldFormats } from 'ui/registry/field_formats'; describe('IP Address Format', function () { diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_source.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_source.js index 4726c3993771e..e254487679574 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_source.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_source.js @@ -19,7 +19,7 @@ import $ from 'jquery'; import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { fieldFormats } from 'ui/registry/field_formats'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_string.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_string.js index c779c164b7d16..e4e11e288d1f4 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_string.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_string.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { fieldFormats } from 'ui/registry/field_formats'; describe('String Format', function () { diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_truncate.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_truncate.js index d5c89f98182b8..0db4c844e2917 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_truncate.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_truncate.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { fieldFormats } from 'ui/registry/field_formats'; describe('String Truncate Format', function () { diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_url.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_url.js index e00131caa84db..b62ba4b147cf2 100644 --- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_url.js +++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_url.js @@ -18,7 +18,7 @@ */ import $ from 'jquery'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { fieldFormats } from 'ui/registry/field_formats'; describe('Url Format', function () { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js index f3b15caa92637..d12e0649ec8c5 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { DEFAULT_CATEGORY } from '../default_category'; describe('Settings', function () { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js index 59606b6677b40..e71cf3459a8da 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getAriaName } from '../get_aria_name'; describe('Settings', function () { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js index 939eca86afed2..d517e82395373 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getCategoryName } from '../get_category_name'; describe('Settings', function () { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js index 212e9c94f37e9..ac6436590fd9b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getValType } from '../get_val_type'; describe('Settings', function () { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js index d668c6ff1dbc8..043230d5f9eab 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isDefaultValue } from '../is_default_value'; describe('Settings', function () { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js index 428b9852ff842..ad1ba30ece4b1 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { toEditableConfig } from '../to_editable_config'; describe('Settings', function () { diff --git a/src/legacy/core_plugins/kibana/server/lib/__tests__/handle_es_error.js b/src/legacy/core_plugins/kibana/server/lib/__tests__/handle_es_error.js index a3cd660687897..c8ce291af0cae 100644 --- a/src/legacy/core_plugins/kibana/server/lib/__tests__/handle_es_error.js +++ b/src/legacy/core_plugins/kibana/server/lib/__tests__/handle_es_error.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import handleESError from '../handle_es_error'; import { errors as esErrors } from 'elasticsearch'; diff --git a/src/legacy/core_plugins/kibana/server/lib/__tests__/manage_uuid.js b/src/legacy/core_plugins/kibana/server/lib/__tests__/manage_uuid.js index 80fa79ab64f55..907b2c8e95f8a 100644 --- a/src/legacy/core_plugins/kibana/server/lib/__tests__/manage_uuid.js +++ b/src/legacy/core_plugins/kibana/server/lib/__tests__/manage_uuid.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { startTestServers } from '../../../../../../test_utils/kbn_server'; import manageUuid from '../manage_uuid'; diff --git a/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js b/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js index 42845b4cf0eb1..1ef1a1f19218a 100644 --- a/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js +++ b/src/legacy/core_plugins/kibana/server/lib/__tests__/relationships.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { findRelationships } from '../management/saved_objects/relationships'; describe('findRelationships', () => { diff --git a/src/legacy/core_plugins/kibana/server/lib/__tests__/system_api.js b/src/legacy/core_plugins/kibana/server/lib/__tests__/system_api.js index c8b9cefc5aa1b..f575918777568 100644 --- a/src/legacy/core_plugins/kibana/server/lib/__tests__/system_api.js +++ b/src/legacy/core_plugins/kibana/server/lib/__tests__/system_api.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isSystemApiRequest } from '../system_api'; describe('system_api', () => { diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.test.js b/src/legacy/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.test.js index 108ed4c713300..13e5b4711f488 100644 --- a/src/legacy/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.test.js +++ b/src/legacy/core_plugins/kibana/server/tutorials/apm/saved_objects/get_saved_objects.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getSavedObjects } from './get_saved_objects'; const indexPatternTitle = 'dynamic index pattern title'; diff --git a/src/legacy/core_plugins/metric_vis/public/__tests__/metric_vis.js b/src/legacy/core_plugins/metric_vis/public/__tests__/metric_vis.js index 43def2fe543a1..a8bfec6c86203 100644 --- a/src/legacy/core_plugins/metric_vis/public/__tests__/metric_vis.js +++ b/src/legacy/core_plugins/metric_vis/public/__tests__/metric_vis.js @@ -19,7 +19,7 @@ import $ from 'jquery'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VisProvider } from 'ui/vis'; import LogstashIndexPatternStubProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js b/src/legacy/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js index 470669f3f5688..82ef6f2de50be 100644 --- a/src/legacy/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js +++ b/src/legacy/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { MetricVisComponent } from '../metric_vis_controller'; describe('metric vis controller', function () { diff --git a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js index 54a2e018983ab..c223660f869ba 100644 --- a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; import { RegionMapsVisualizationProvider } from '../region_map_visualization'; diff --git a/src/legacy/core_plugins/table_vis/public/__tests__/_table_vis_controller.js b/src/legacy/core_plugins/table_vis/public/__tests__/_table_vis_controller.js index 41028de007833..ac46ec373f9f0 100644 --- a/src/legacy/core_plugins/table_vis/public/__tests__/_table_vis_controller.js +++ b/src/legacy/core_plugins/table_vis/public/__tests__/_table_vis_controller.js @@ -18,7 +18,7 @@ */ import $ from 'jquery'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { LegacyResponseHandlerProvider } from 'ui/vis/response_handlers/legacy'; import { VisProvider } from 'ui/vis'; diff --git a/src/legacy/core_plugins/tagcloud/public/__tests__/tag_cloud.js b/src/legacy/core_plugins/tagcloud/public/__tests__/tag_cloud.js index 441d2bb002cb9..f6736b5d3d116 100644 --- a/src/legacy/core_plugins/tagcloud/public/__tests__/tag_cloud.js +++ b/src/legacy/core_plugins/tagcloud/public/__tests__/tag_cloud.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; import TagCloud from '../tag_cloud'; import d3 from 'd3'; diff --git a/src/legacy/core_plugins/tagcloud/public/__tests__/tag_cloud_visualization.js b/src/legacy/core_plugins/tagcloud/public/__tests__/tag_cloud_visualization.js index 9a0e904ccc715..69d08d8cb3f74 100644 --- a/src/legacy/core_plugins/tagcloud/public/__tests__/tag_cloud_visualization.js +++ b/src/legacy/core_plugins/tagcloud/public/__tests__/tag_cloud_visualization.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import LogstashIndexPatternStubProvider from 'fixtures/stubbed_logstash_index_pattern'; import * as visModule from 'ui/vis'; diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js index 3d83fdfe12aa8..608ded804e5a7 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { CoordinateMapsVisualizationProvider } from '../coordinate_maps_visualization'; import LogstashIndexPatternStubProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js b/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js index e5a73e734ddde..628175e4fd2b3 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { KibanaMap } from 'ui/vis/map/kibana_map'; import { GeohashLayer } from '../geohash_layer'; // import heatmapPng from './heatmap.png'; diff --git a/src/legacy/core_plugins/timelion/public/__tests__/_tick_generator.js b/src/legacy/core_plugins/timelion/public/__tests__/_tick_generator.js index 3d7a62ea1b2f6..508cc5cd856d2 100644 --- a/src/legacy/core_plugins/timelion/public/__tests__/_tick_generator.js +++ b/src/legacy/core_plugins/timelion/public/__tests__/_tick_generator.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; describe('Tick Generator', function () { diff --git a/src/legacy/core_plugins/timelion/public/__tests__/services/tick_formatters.js b/src/legacy/core_plugins/timelion/public/__tests__/services/tick_formatters.js index f447ad0adf1aa..8e140b9bf992a 100644 --- a/src/legacy/core_plugins/timelion/public/__tests__/services/tick_formatters.js +++ b/src/legacy/core_plugins/timelion/public/__tests__/services/tick_formatters.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; describe('Tick Formatters', function () { diff --git a/src/legacy/core_plugins/timelion/public/directives/__tests__/timelion_expression_input_helpers.js b/src/legacy/core_plugins/timelion/public/directives/__tests__/timelion_expression_input_helpers.js index 7f8ca9a136f53..16f44e2835b21 100644 --- a/src/legacy/core_plugins/timelion/public/directives/__tests__/timelion_expression_input_helpers.js +++ b/src/legacy/core_plugins/timelion/public/directives/__tests__/timelion_expression_input_helpers.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import PEG from 'pegjs'; import grammar from 'raw-loader!../../chain.peg'; import { diff --git a/src/legacy/core_plugins/timelion/public/directives/timelion_expression_suggestions/__tests__/timelion_expression_suggestions.js b/src/legacy/core_plugins/timelion/public/directives/timelion_expression_suggestions/__tests__/timelion_expression_suggestions.js index 1a1ecceabef10..59d77a9ec0f1b 100644 --- a/src/legacy/core_plugins/timelion/public/directives/timelion_expression_suggestions/__tests__/timelion_expression_suggestions.js +++ b/src/legacy/core_plugins/timelion/public/directives/timelion_expression_suggestions/__tests__/timelion_expression_suggestions.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../timelion_expression_suggestions'; diff --git a/src/legacy/core_plugins/timelion/server/lib/offset_time.test.js b/src/legacy/core_plugins/timelion/server/lib/offset_time.test.js index 4a4d524f77735..9250d3898638d 100644 --- a/src/legacy/core_plugins/timelion/server/lib/offset_time.test.js +++ b/src/legacy/core_plugins/timelion/server/lib/offset_time.test.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { preprocessOffset } from './offset_time'; diff --git a/src/legacy/core_plugins/vega/public/__tests__/vega_visualization.js b/src/legacy/core_plugins/vega/public/__tests__/vega_visualization.js index 141bf4d061fd5..d40ba8c345681 100644 --- a/src/legacy/core_plugins/vega/public/__tests__/vega_visualization.js +++ b/src/legacy/core_plugins/vega/public/__tests__/vega_visualization.js @@ -18,7 +18,7 @@ */ import Promise from 'bluebird'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import $ from 'jquery'; import { VegaVisualizationProvider } from '../vega_visualization'; diff --git a/src/legacy/core_plugins/vega/public/data_model/__tests__/es_query_parser.js b/src/legacy/core_plugins/vega/public/data_model/__tests__/es_query_parser.js index af83c75a0fec5..40cbbb203deb8 100644 --- a/src/legacy/core_plugins/vega/public/data_model/__tests__/es_query_parser.js +++ b/src/legacy/core_plugins/vega/public/data_model/__tests__/es_query_parser.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import moment from 'moment'; import { EsQueryParser } from '../es_query_parser'; diff --git a/src/legacy/core_plugins/vega/public/data_model/__tests__/search_cache.js b/src/legacy/core_plugins/vega/public/data_model/__tests__/search_cache.js index 4d712a39af779..57057a74e997a 100644 --- a/src/legacy/core_plugins/vega/public/data_model/__tests__/search_cache.js +++ b/src/legacy/core_plugins/vega/public/data_model/__tests__/search_cache.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SearchCache } from '../search_cache'; describe(`SearchCache`, () => { diff --git a/src/legacy/core_plugins/vega/public/data_model/__tests__/time_cache.js b/src/legacy/core_plugins/vega/public/data_model/__tests__/time_cache.js index 8a7f263970bf4..0ab31fb8c5da8 100644 --- a/src/legacy/core_plugins/vega/public/data_model/__tests__/time_cache.js +++ b/src/legacy/core_plugins/vega/public/data_model/__tests__/time_cache.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { TimeCache } from '../time_cache'; describe(`TimeCache`, () => { diff --git a/src/legacy/core_plugins/vega/public/data_model/__tests__/vega_parser.js b/src/legacy/core_plugins/vega/public/data_model/__tests__/vega_parser.js index de8bb8a5006fc..3fa8af0e04c70 100644 --- a/src/legacy/core_plugins/vega/public/data_model/__tests__/vega_parser.js +++ b/src/legacy/core_plugins/vega/public/data_model/__tests__/vega_parser.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VegaParser } from '../vega_parser'; import { bypassExternalUrlCheck } from '../../vega_view/vega_base_view'; diff --git a/src/legacy/deprecation/__tests__/create_transform.js b/src/legacy/deprecation/__tests__/create_transform.js index 5e8292761c785..0a02a081e41e6 100644 --- a/src/legacy/deprecation/__tests__/create_transform.js +++ b/src/legacy/deprecation/__tests__/create_transform.js @@ -18,7 +18,7 @@ */ import { createTransform } from '../create_transform'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; describe('deprecation', function () { diff --git a/src/legacy/deprecation/deprecations/__tests__/rename.js b/src/legacy/deprecation/deprecations/__tests__/rename.js index 5a1d60a65bf97..eb7b0f6449325 100644 --- a/src/legacy/deprecation/deprecations/__tests__/rename.js +++ b/src/legacy/deprecation/deprecations/__tests__/rename.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { rename } from '../rename'; import sinon from 'sinon'; diff --git a/src/legacy/deprecation/deprecations/__tests__/unused.js b/src/legacy/deprecation/deprecations/__tests__/unused.js index cda113442ca79..41e4e9192f83d 100644 --- a/src/legacy/deprecation/deprecations/__tests__/unused.js +++ b/src/legacy/deprecation/deprecations/__tests__/unused.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { unused } from '../unused'; diff --git a/src/legacy/plugin_discovery/__tests__/find_plugin_specs.js b/src/legacy/plugin_discovery/__tests__/find_plugin_specs.js index 563ea9043fce8..f8d1cfc865a1e 100644 --- a/src/legacy/plugin_discovery/__tests__/find_plugin_specs.js +++ b/src/legacy/plugin_discovery/__tests__/find_plugin_specs.js @@ -20,7 +20,7 @@ import { resolve } from 'path'; import { toArray } from 'rxjs/operators'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isEqual } from 'lodash'; import { findPluginSpecs } from '../find_plugin_specs'; import { PluginSpec } from '../plugin_spec'; diff --git a/src/legacy/plugin_discovery/plugin_config/__tests__/extend_config_service.js b/src/legacy/plugin_discovery/plugin_config/__tests__/extend_config_service.js index a7028b73d704d..e0c965ee6c4bb 100644 --- a/src/legacy/plugin_discovery/plugin_config/__tests__/extend_config_service.js +++ b/src/legacy/plugin_discovery/plugin_config/__tests__/extend_config_service.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Config } from '../../../server/config'; import { PluginPack } from '../../plugin_pack'; diff --git a/src/legacy/plugin_discovery/plugin_config/__tests__/schema.js b/src/legacy/plugin_discovery/plugin_config/__tests__/schema.js index 2e00936653d0d..fb768a0335531 100644 --- a/src/legacy/plugin_discovery/plugin_config/__tests__/schema.js +++ b/src/legacy/plugin_discovery/plugin_config/__tests__/schema.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PluginPack } from '../../plugin_pack'; import { getSchema, getStubSchema } from '../schema'; diff --git a/src/legacy/plugin_discovery/plugin_config/__tests__/settings.js b/src/legacy/plugin_discovery/plugin_config/__tests__/settings.js index 780f48165f1b7..a53ada44fad48 100644 --- a/src/legacy/plugin_discovery/plugin_config/__tests__/settings.js +++ b/src/legacy/plugin_discovery/plugin_config/__tests__/settings.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { PluginPack } from '../../plugin_pack'; diff --git a/src/legacy/plugin_discovery/plugin_exports/__tests__/reduce_export_specs.js b/src/legacy/plugin_discovery/plugin_exports/__tests__/reduce_export_specs.js index 6635cfcbc43e9..7df87ca5cc5db 100644 --- a/src/legacy/plugin_discovery/plugin_exports/__tests__/reduce_export_specs.js +++ b/src/legacy/plugin_discovery/plugin_exports/__tests__/reduce_export_specs.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PluginPack } from '../../plugin_pack'; import { reduceExportSpecs } from '../reduce_export_specs'; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/create_pack.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/create_pack.js index 740b4ebed63af..3a39b5d0182c0 100644 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/create_pack.js +++ b/src/legacy/plugin_discovery/plugin_pack/__tests__/create_pack.js @@ -20,7 +20,7 @@ import { resolve } from 'path'; import * as Rx from 'rxjs'; import { toArray } from 'rxjs/operators'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createPack$ } from '../create_pack'; import { PluginPack } from '../plugin_pack'; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/package_json_at_path.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/package_json_at_path.js index 59ac6050f803b..008a5d3299cce 100644 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/package_json_at_path.js +++ b/src/legacy/plugin_discovery/plugin_pack/__tests__/package_json_at_path.js @@ -20,7 +20,7 @@ import { resolve } from 'path'; import { toArray } from 'rxjs/operators'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createPackageJsonAtPath$ } from '../package_json_at_path'; import { diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/package_jsons_in_directory.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/package_jsons_in_directory.js index f86cbd3bb6c1a..93bc69e2d3bd4 100644 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/package_jsons_in_directory.js +++ b/src/legacy/plugin_discovery/plugin_pack/__tests__/package_jsons_in_directory.js @@ -20,7 +20,7 @@ import { resolve } from 'path'; import { toArray } from 'rxjs/operators'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createPackageJsonsInDirectory$ } from '../package_jsons_in_directory'; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/plugin_pack.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/plugin_pack.js index d4ced575a6ead..425f026ef3b92 100644 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/plugin_pack.js +++ b/src/legacy/plugin_discovery/plugin_pack/__tests__/plugin_pack.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { PluginPack } from '../plugin_pack'; diff --git a/src/legacy/plugin_discovery/plugin_spec/__tests__/is_version_compatible.js b/src/legacy/plugin_discovery/plugin_spec/__tests__/is_version_compatible.js index 637fc0422cdf5..897184496af37 100644 --- a/src/legacy/plugin_discovery/plugin_spec/__tests__/is_version_compatible.js +++ b/src/legacy/plugin_discovery/plugin_spec/__tests__/is_version_compatible.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isVersionCompatible } from '../is_version_compatible'; diff --git a/src/legacy/plugin_discovery/plugin_spec/__tests__/plugin_spec.js b/src/legacy/plugin_discovery/plugin_spec/__tests__/plugin_spec.js index 6709e4996f6f9..dc57e0a099d05 100644 --- a/src/legacy/plugin_discovery/plugin_spec/__tests__/plugin_spec.js +++ b/src/legacy/plugin_discovery/plugin_spec/__tests__/plugin_spec.js @@ -19,7 +19,7 @@ import { resolve } from 'path'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { PluginPack } from '../../plugin_pack'; diff --git a/src/legacy/server/config/__tests__/deprecation_warnings.js b/src/legacy/server/config/__tests__/deprecation_warnings.js index 6e4d5e2fd57d7..ecaa6fa22f54c 100644 --- a/src/legacy/server/config/__tests__/deprecation_warnings.js +++ b/src/legacy/server/config/__tests__/deprecation_warnings.js @@ -19,7 +19,7 @@ import { spawn } from 'child_process'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const RUN_KBN_SERVER_STARTUP = require.resolve('./fixtures/run_kbn_server_startup'); const SETUP_NODE_ENV = require.resolve('../../../../setup_node_env'); diff --git a/src/legacy/server/usage/classes/__tests__/collector_set.js b/src/legacy/server/usage/classes/__tests__/collector_set.js index 3d1a23b8dc5d6..bdd490ab6f221 100644 --- a/src/legacy/server/usage/classes/__tests__/collector_set.js +++ b/src/legacy/server/usage/classes/__tests__/collector_set.js @@ -19,7 +19,7 @@ import { noop } from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Collector } from '../collector'; import { CollectorSet } from '../collector_set'; diff --git a/src/legacy/ui/__tests__/ui_exports_replace_injected_vars.js b/src/legacy/ui/__tests__/ui_exports_replace_injected_vars.js index f75ac5d09f164..9243a715625d8 100644 --- a/src/legacy/ui/__tests__/ui_exports_replace_injected_vars.js +++ b/src/legacy/ui/__tests__/ui_exports_replace_injected_vars.js @@ -20,7 +20,7 @@ import { resolve } from 'path'; import { delay } from 'bluebird'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import cheerio from 'cheerio'; import { noop } from 'lodash'; diff --git a/src/legacy/ui/field_formats/__tests__/field_format.js b/src/legacy/ui/field_formats/__tests__/field_format.js index 7bd7e7e225db4..bf8ff9f33b18c 100644 --- a/src/legacy/ui/field_formats/__tests__/field_format.js +++ b/src/legacy/ui/field_formats/__tests__/field_format.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { asPrettyString } from '../../../core_plugins/kibana/common/utils/as_pretty_string'; import { FieldFormat } from '../field_format'; diff --git a/src/legacy/ui/field_formats/__tests__/field_formats_mixin.js b/src/legacy/ui/field_formats/__tests__/field_formats_mixin.js index 3159705f3d8ed..8f513fe28c98b 100644 --- a/src/legacy/ui/field_formats/__tests__/field_formats_mixin.js +++ b/src/legacy/ui/field_formats/__tests__/field_formats_mixin.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { FieldFormat } from '../field_format'; diff --git a/src/legacy/ui/field_formats/__tests__/field_formats_service.js b/src/legacy/ui/field_formats/__tests__/field_formats_service.js index 2110859f53551..9ae80462c2a07 100644 --- a/src/legacy/ui/field_formats/__tests__/field_formats_service.js +++ b/src/legacy/ui/field_formats/__tests__/field_formats_service.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { FieldFormat } from '../field_format'; import { FieldFormatsService } from '../field_formats_service'; import { createNumberFormat } from '../../../core_plugins/kibana/common/field_formats/types/number'; diff --git a/src/legacy/ui/public/__tests__/errors.js b/src/legacy/ui/public/__tests__/errors.js index d328a6dc4e0ca..cc861ffd8e969 100644 --- a/src/legacy/ui/public/__tests__/errors.js +++ b/src/legacy/ui/public/__tests__/errors.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { RequestFailure, FetchFailure, diff --git a/src/legacy/ui/public/__tests__/metadata.js b/src/legacy/ui/public/__tests__/metadata.js index 9cb5841f0d409..56866efcbc27d 100644 --- a/src/legacy/ui/public/__tests__/metadata.js +++ b/src/legacy/ui/public/__tests__/metadata.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { metadata } from '../metadata'; describe('ui/metadata', () => { it('is immutable', () => { diff --git a/src/legacy/ui/public/accessibility/__tests__/kbn_accessible_click.js b/src/legacy/ui/public/accessibility/__tests__/kbn_accessible_click.js index 93b3f5b094e65..b120a1c6fff36 100644 --- a/src/legacy/ui/public/accessibility/__tests__/kbn_accessible_click.js +++ b/src/legacy/ui/public/accessibility/__tests__/kbn_accessible_click.js @@ -19,7 +19,7 @@ import angular from 'angular'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../kbn_accessible_click'; import { keyCodes } from '@elastic/eui'; diff --git a/src/legacy/ui/public/accessibility/__tests__/kbn_ui_ace_keyboard_mode.js b/src/legacy/ui/public/accessibility/__tests__/kbn_ui_ace_keyboard_mode.js index 7845284479953..a8a6f0cd0db2f 100644 --- a/src/legacy/ui/public/accessibility/__tests__/kbn_ui_ace_keyboard_mode.js +++ b/src/legacy/ui/public/accessibility/__tests__/kbn_ui_ace_keyboard_mode.js @@ -19,7 +19,7 @@ import angular from 'angular'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../kbn_ui_ace_keyboard_mode'; import { keyCodes } from '@elastic/eui'; diff --git a/src/legacy/ui/public/accessibility/__tests__/scrollto_activedescendant.js b/src/legacy/ui/public/accessibility/__tests__/scrollto_activedescendant.js index f843c7f865791..38091d45ff9af 100644 --- a/src/legacy/ui/public/accessibility/__tests__/scrollto_activedescendant.js +++ b/src/legacy/ui/public/accessibility/__tests__/scrollto_activedescendant.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../scrollto_activedescendant'; diff --git a/src/legacy/ui/public/agg_response/hierarchical/__tests__/collect_branch.js b/src/legacy/ui/public/agg_response/hierarchical/__tests__/collect_branch.js index 02417e35cae40..310247657f0cd 100644 --- a/src/legacy/ui/public/agg_response/hierarchical/__tests__/collect_branch.js +++ b/src/legacy/ui/public/agg_response/hierarchical/__tests__/collect_branch.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import collectBranch from '../_collect_branch'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('collectBranch()', function () { let results; const convert = function (name) { diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_add_to_siri.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_add_to_siri.js index 7365f30511b35..8c2efbd608ed9 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_add_to_siri.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_add_to_siri.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { addToSiri } from '../_add_to_siri'; describe('addToSiri', function () { diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js index 7aa75105704c8..3ae59d1639b05 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { makeFakeXAspect } from '../_fake_x_aspect'; describe('makeFakeXAspect', function () { diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_aspects.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_get_aspects.js index ad4e04fa2aaed..45b32084a4d20 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_aspects.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_get_aspects.js @@ -18,7 +18,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getAspects } from '../_get_aspects'; describe('getAspects', function () { diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_point.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_get_point.js index 98d5c7c317619..bde46b3b4be17 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_point.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_get_point.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getPoint } from '../_get_point'; describe('getPoint', function () { diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_series.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_get_series.js index 68e212bd8c159..6eee6e21a9849 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_series.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_get_series.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getSeries } from '../_get_series'; diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_init_x_axis.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_init_x_axis.js index 83314d2ca1cf1..93ed9c2cc18dd 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_init_x_axis.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_init_x_axis.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { initXAxis } from '../_init_x_axis'; import { makeFakeXAspect } from '../_fake_x_aspect'; diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_init_y_axis.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_init_y_axis.js index 5a730a78cfdd1..a05c019b7e4be 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_init_y_axis.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_init_y_axis.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { initYAxis } from '../_init_y_axis'; describe('initYAxis', function () { diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_main.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_main.js index ba6f82c9bc70e..470a03ef0ffd6 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_main.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_main.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { buildPointSeriesData } from '../point_series'; describe('pointSeriesChartDataFromTable', function () { diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_ordered_date_axis.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_ordered_date_axis.js index ea08ca56d28bb..f689c0b8d8aa5 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_ordered_date_axis.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_ordered_date_axis.js @@ -19,7 +19,7 @@ import moment from 'moment'; import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { orderedDateAxis } from '../_ordered_date_axis'; describe('orderedDateAxis', function () { diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_tooltip_formatter.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_tooltip_formatter.js index c431e0ed9ee03..472836af52b90 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_tooltip_formatter.js +++ b/src/legacy/ui/public/agg_response/point_series/__tests__/_tooltip_formatter.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import $ from 'jquery'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { PointSeriesTooltipFormatter } from '../_tooltip_formatter'; diff --git a/src/legacy/ui/public/agg_response/tabify/__tests__/_buckets.js b/src/legacy/ui/public/agg_response/tabify/__tests__/_buckets.js index dfc475a949b43..9d17a508223a2 100644 --- a/src/legacy/ui/public/agg_response/tabify/__tests__/_buckets.js +++ b/src/legacy/ui/public/agg_response/tabify/__tests__/_buckets.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { TabifyBuckets } from '../_buckets'; describe('Buckets wrapper', function () { diff --git a/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js b/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js index fbc42aaa04c37..4e15f8cc4e619 100644 --- a/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js +++ b/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { tabifyGetColumns } from '../_get_columns'; import { VisProvider } from '../../../vis'; diff --git a/src/legacy/ui/public/agg_response/tabify/__tests__/_integration.js b/src/legacy/ui/public/agg_response/tabify/__tests__/_integration.js index ad6732add3542..c11f38f38298c 100644 --- a/src/legacy/ui/public/agg_response/tabify/__tests__/_integration.js +++ b/src/legacy/ui/public/agg_response/tabify/__tests__/_integration.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import fixtures from 'fixtures/fake_hierarchical_data'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { tabifyAggResponse } from '../tabify'; import { VisProvider } from '../../../vis'; diff --git a/src/legacy/ui/public/agg_response/tabify/__tests__/_response_writer.js b/src/legacy/ui/public/agg_response/tabify/__tests__/_response_writer.js index b395467146762..09668c638d695 100644 --- a/src/legacy/ui/public/agg_response/tabify/__tests__/_response_writer.js +++ b/src/legacy/ui/public/agg_response/tabify/__tests__/_response_writer.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { TabbedAggResponseWriter } from '../_response_writer'; import { VisProvider } from '../../../vis'; diff --git a/src/legacy/ui/public/agg_table/__tests__/_group.js b/src/legacy/ui/public/agg_table/__tests__/_group.js index cd0a432006fc4..89c21f9169be8 100644 --- a/src/legacy/ui/public/agg_table/__tests__/_group.js +++ b/src/legacy/ui/public/agg_table/__tests__/_group.js @@ -19,7 +19,7 @@ import $ from 'jquery'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; import { LegacyResponseHandlerProvider } from '../../vis/response_handlers/legacy'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/agg_table/__tests__/_table.js b/src/legacy/ui/public/agg_table/__tests__/_table.js index 299da94902143..357d473de47c1 100644 --- a/src/legacy/ui/public/agg_table/__tests__/_table.js +++ b/src/legacy/ui/public/agg_table/__tests__/_table.js @@ -20,7 +20,7 @@ import $ from 'jquery'; import moment from 'moment'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; import sinon from 'sinon'; import { LegacyResponseHandlerProvider } from '../../vis/response_handlers/legacy'; diff --git a/src/legacy/ui/public/agg_types/__tests__/agg_params.js b/src/legacy/ui/public/agg_types/__tests__/agg_params.js index bddfa725165ad..99a9347c934a6 100644 --- a/src/legacy/ui/public/agg_types/__tests__/agg_params.js +++ b/src/legacy/ui/public/agg_types/__tests__/agg_params.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { AggParams } from '../agg_params'; import { BaseParamType } from '../param_types/base'; import { FieldParamType } from '../param_types/field'; diff --git a/src/legacy/ui/public/agg_types/__tests__/agg_type.js b/src/legacy/ui/public/agg_types/__tests__/agg_type.js index 659809175db82..496e5515c75ef 100644 --- a/src/legacy/ui/public/agg_types/__tests__/agg_type.js +++ b/src/legacy/ui/public/agg_types/__tests__/agg_type.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../private'; import { AggParams } from '../agg_params'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/_geo_hash.js b/src/legacy/ui/public/agg_types/__tests__/buckets/_geo_hash.js index 041030a9afb2a..39c27f0b8db24 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/_geo_hash.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/_geo_hash.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { geoHashBucketAgg } from '../../buckets/geo_hash'; import * as AggConfigModule from '../../../vis/agg_config'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/_histogram.js b/src/legacy/ui/public/agg_types/__tests__/buckets/_histogram.js index 02b33cf7059eb..9de472e91fc88 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/_histogram.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/_histogram.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import ngMock from 'ng_mock'; import { aggTypes } from '../..'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/_range.js index bbfc46eee1813..8aabf464e7b1c 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/_range.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/_range.js @@ -19,7 +19,7 @@ import { values } from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import resp from 'fixtures/agg_resp/range'; import { VisProvider } from '../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js b/src/legacy/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js index 3ea1c45d42897..d6840699074b4 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { buildOtherBucketAgg, mergeOtherBucketAggResponse, updateMissingBucket } from '../../buckets/_terms_other_bucket_helper'; import { VisProvider } from '../../../vis'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js index df6b9ed9ec807..a02da38511dfa 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_histogram.js @@ -21,7 +21,7 @@ import _ from 'lodash'; import moment from 'moment'; import aggResp from 'fixtures/agg_resp/date_histogram'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { createFilterDateHistogram } from '../../../buckets/create_filter/date_histogram'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js index f2344bb38c178..b6557ed6d762f 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/date_range.js @@ -18,7 +18,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import moment from 'moment'; import { VisProvider } from '../../../../vis'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/filters.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/filters.js index abe6be806c68a..01337f2725045 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/filters.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/filters.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js index df729aa371b10..23e66cf5f1ae7 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/histogram.js @@ -18,7 +18,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js index fb08d5ca6e36d..cbab24745acd7 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/ip_range.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/range.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/range.js index bc7bd22ee8287..58e7e0203c596 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/range.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/range.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/terms.js b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/terms.js index 9195df7b1b662..8753806babfa2 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/terms.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/create_filter/terms.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js b/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js index afacdc522562e..69d898be5c438 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_editor.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import $ from 'jquery'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { VisProvider } from '../../../../vis'; import { intervalOptions } from '../../../buckets/_interval_options'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js b/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js index 394ff6e526907..856da584cb68f 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import moment from 'moment'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import ngMock from 'ng_mock'; import AggParamWriterProvider from '../../agg_param_writer'; diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/terms.js b/src/legacy/ui/public/agg_types/__tests__/buckets/terms.js index 923f662451240..a5ddb1849bdbf 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/terms.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/terms.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { aggTypes } from '../..'; diff --git a/src/legacy/ui/public/agg_types/__tests__/controls/number_list.js b/src/legacy/ui/public/agg_types/__tests__/controls/number_list.js index bbbdb822e0be4..12856b3363bf8 100644 --- a/src/legacy/ui/public/agg_types/__tests__/controls/number_list.js +++ b/src/legacy/ui/public/agg_types/__tests__/controls/number_list.js @@ -18,7 +18,7 @@ */ import $ from 'jquery'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import simulateKeys from 'test_utils/simulate_keys'; import ngMock from 'ng_mock'; import '../../../number_list'; diff --git a/src/legacy/ui/public/agg_types/__tests__/directives/auto_select_if_only_one.js b/src/legacy/ui/public/agg_types/__tests__/directives/auto_select_if_only_one.js index 94bbb2addebe0..9e83243811d95 100644 --- a/src/legacy/ui/public/agg_types/__tests__/directives/auto_select_if_only_one.js +++ b/src/legacy/ui/public/agg_types/__tests__/directives/auto_select_if_only_one.js @@ -18,7 +18,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../directives/auto_select_if_only_one'; diff --git a/src/legacy/ui/public/agg_types/__tests__/directives/input_number.js b/src/legacy/ui/public/agg_types/__tests__/directives/input_number.js index 6d3a3bf19fb35..5d7937f5275a3 100644 --- a/src/legacy/ui/public/agg_types/__tests__/directives/input_number.js +++ b/src/legacy/ui/public/agg_types/__tests__/directives/input_number.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../directives/input_number'; diff --git a/src/legacy/ui/public/agg_types/__tests__/directives/validate_cidr_mask.js b/src/legacy/ui/public/agg_types/__tests__/directives/validate_cidr_mask.js index 05dffe754a99a..3d5d2531ee85f 100644 --- a/src/legacy/ui/public/agg_types/__tests__/directives/validate_cidr_mask.js +++ b/src/legacy/ui/public/agg_types/__tests__/directives/validate_cidr_mask.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../directives/validate_cidr_mask'; diff --git a/src/legacy/ui/public/agg_types/__tests__/directives/validate_date_math.js b/src/legacy/ui/public/agg_types/__tests__/directives/validate_date_math.js index 39bab01c96f97..5f264386a1fbc 100644 --- a/src/legacy/ui/public/agg_types/__tests__/directives/validate_date_math.js +++ b/src/legacy/ui/public/agg_types/__tests__/directives/validate_date_math.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../directives/validate_date_math'; diff --git a/src/legacy/ui/public/agg_types/__tests__/directives/validate_ip.js b/src/legacy/ui/public/agg_types/__tests__/directives/validate_ip.js index 625ff4183519f..ad4c91e9081bf 100644 --- a/src/legacy/ui/public/agg_types/__tests__/directives/validate_ip.js +++ b/src/legacy/ui/public/agg_types/__tests__/directives/validate_ip.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../directives/validate_ip'; diff --git a/src/legacy/ui/public/agg_types/__tests__/index.js b/src/legacy/ui/public/agg_types/__tests__/index.js index 0af05397cdc08..321fe0fa27f46 100644 --- a/src/legacy/ui/public/agg_types/__tests__/index.js +++ b/src/legacy/ui/public/agg_types/__tests__/index.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import './agg_type'; import './agg_params'; import './buckets/_histogram'; diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/lib/make_nested_label.js b/src/legacy/ui/public/agg_types/__tests__/metrics/lib/make_nested_label.js index d5bff445dc137..f122a48c29313 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/lib/make_nested_label.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/lib/make_nested_label.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { makeNestedLabel } from '../../../metrics/lib/make_nested_label'; describe('metric agg make_nested_label', function () { diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/median.js b/src/legacy/ui/public/agg_types/__tests__/metrics/median.js index de81913494bae..eb1abd7450115 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/median.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/median.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VisProvider } from '../../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/parent_pipeline.js b/src/legacy/ui/public/agg_types/__tests__/metrics/parent_pipeline.js index 78a9ad4d10797..606080627d86b 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/parent_pipeline.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/parent_pipeline.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import ngMock from 'ng_mock'; import { derivativeMetricAgg } from '../../metrics/derivative'; diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/percentile_ranks.js b/src/legacy/ui/public/agg_types/__tests__/metrics/percentile_ranks.js index ba0f8eef5ffb1..3e3ee89b14d10 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/percentile_ranks.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/percentile_ranks.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { percentileRanksMetricAgg } from '../../metrics/percentile_ranks'; import { VisProvider } from '../../../vis'; diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/percentiles.js b/src/legacy/ui/public/agg_types/__tests__/metrics/percentiles.js index b26ffe2168e65..cd790729783d3 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/percentiles.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/percentiles.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { percentilesMetricAgg } from '../../metrics/percentiles'; import { VisProvider } from '../../../vis'; diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js b/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js index 43ae223eaf17e..c80f7f6a9ad2c 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import ngMock from 'ng_mock'; import { bucketSumMetricAgg } from '../../metrics/bucket_sum'; diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/std_deviation.js b/src/legacy/ui/public/agg_types/__tests__/metrics/std_deviation.js index c012d9c1f29d3..181fc9e9b37c4 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/std_deviation.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/std_deviation.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { stdDeviationMetricAgg } from '../../metrics/std_deviation'; import { VisProvider } from '../../../vis'; diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js b/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js index 01fc774b2d49a..d206b8f47df9b 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { topHitMetricAgg } from '../../metrics/top_hit'; import { VisProvider } from '../../../vis'; diff --git a/src/legacy/ui/public/agg_types/__tests__/param_types/_field.js b/src/legacy/ui/public/agg_types/__tests__/param_types/_field.js index 01eab6866718b..94a976f98e984 100644 --- a/src/legacy/ui/public/agg_types/__tests__/param_types/_field.js +++ b/src/legacy/ui/public/agg_types/__tests__/param_types/_field.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { reject } from 'lodash'; import ngMock from 'ng_mock'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/agg_types/__tests__/param_types/_json.js b/src/legacy/ui/public/agg_types/__tests__/param_types/_json.js index 516f1c95d71ff..efac833cb061b 100644 --- a/src/legacy/ui/public/agg_types/__tests__/param_types/_json.js +++ b/src/legacy/ui/public/agg_types/__tests__/param_types/_json.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { BaseParamType } from '../../param_types/base'; import { JsonParamType } from '../../param_types/json'; diff --git a/src/legacy/ui/public/agg_types/__tests__/param_types/_optioned.js b/src/legacy/ui/public/agg_types/__tests__/param_types/_optioned.js index 0491976665c76..4e66f6cfbd41b 100644 --- a/src/legacy/ui/public/agg_types/__tests__/param_types/_optioned.js +++ b/src/legacy/ui/public/agg_types/__tests__/param_types/_optioned.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { BaseParamType } from '../../param_types/base'; import { OptionedParamType } from '../../param_types/optioned'; diff --git a/src/legacy/ui/public/agg_types/__tests__/param_types/_regex.js b/src/legacy/ui/public/agg_types/__tests__/param_types/_regex.js index acfb7d248f114..896a9241dbfc7 100644 --- a/src/legacy/ui/public/agg_types/__tests__/param_types/_regex.js +++ b/src/legacy/ui/public/agg_types/__tests__/param_types/_regex.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { BaseParamType } from '../../param_types/base'; import { RegexParamType } from '../../param_types/regex'; diff --git a/src/legacy/ui/public/agg_types/__tests__/param_types/_string.js b/src/legacy/ui/public/agg_types/__tests__/param_types/_string.js index e11c50077a9c8..261b974279802 100644 --- a/src/legacy/ui/public/agg_types/__tests__/param_types/_string.js +++ b/src/legacy/ui/public/agg_types/__tests__/param_types/_string.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { BaseParamType } from '../../param_types/base'; import { StringParamType } from '../../param_types/string'; diff --git a/src/legacy/ui/public/bind/__tests__/bind.js b/src/legacy/ui/public/bind/__tests__/bind.js index ce59076df923d..e439ea7dbcdda 100644 --- a/src/legacy/ui/public/bind/__tests__/bind.js +++ b/src/legacy/ui/public/bind/__tests__/bind.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; describe('$scope.$bind', function () { diff --git a/src/legacy/ui/public/binder/__tests__/binder.js b/src/legacy/ui/public/binder/__tests__/binder.js index 3a0ddff2137a4..703b9ec413313 100644 --- a/src/legacy/ui/public/binder/__tests__/binder.js +++ b/src/legacy/ui/public/binder/__tests__/binder.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { Binder } from '..'; diff --git a/src/legacy/ui/public/chrome/__tests__/nav_controls.js b/src/legacy/ui/public/chrome/__tests__/nav_controls.js index cf664b943190c..9d43d83248703 100644 --- a/src/legacy/ui/public/chrome/__tests__/nav_controls.js +++ b/src/legacy/ui/public/chrome/__tests__/nav_controls.js @@ -19,7 +19,7 @@ import ngMock from 'ng_mock'; import $ from 'jquery'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { chromeNavControlsRegistry } from '../../registry/chrome_nav_controls'; import { uiRegistry } from '../../registry/_registry'; diff --git a/src/legacy/ui/public/chrome/api/__tests__/apps.js b/src/legacy/ui/public/chrome/api/__tests__/apps.js index e640d1717c2cb..8515332efa36f 100644 --- a/src/legacy/ui/public/chrome/api/__tests__/apps.js +++ b/src/legacy/ui/public/chrome/api/__tests__/apps.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import setup from '../apps'; diff --git a/src/legacy/ui/public/chrome/api/__tests__/nav.js b/src/legacy/ui/public/chrome/api/__tests__/nav.js index 4b42c33ec8227..faf43058259e8 100644 --- a/src/legacy/ui/public/chrome/api/__tests__/nav.js +++ b/src/legacy/ui/public/chrome/api/__tests__/nav.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { initChromeNavApi } from '../nav'; import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; diff --git a/src/legacy/ui/public/chrome/api/__tests__/xsrf.js b/src/legacy/ui/public/chrome/api/__tests__/xsrf.js index 27b8a400adf47..52da8fb545c7d 100644 --- a/src/legacy/ui/public/chrome/api/__tests__/xsrf.js +++ b/src/legacy/ui/public/chrome/api/__tests__/xsrf.js @@ -18,7 +18,7 @@ */ import $ from 'jquery'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import ngMock from 'ng_mock'; diff --git a/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js b/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js index fc411b5638b3b..5ce42b9c72916 100644 --- a/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js +++ b/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SubUrlRouteFilterProvider } from '../sub_url_route_filter'; diff --git a/src/legacy/ui/public/config/__tests__/config.js b/src/legacy/ui/public/config/__tests__/config.js index 55dcbd65880f8..52a573417f3c5 100644 --- a/src/legacy/ui/public/config/__tests__/config.js +++ b/src/legacy/ui/public/config/__tests__/config.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import ngMock from 'ng_mock'; diff --git a/src/legacy/ui/public/courier/fetch/__tests__/call_client.js b/src/legacy/ui/public/courier/fetch/__tests__/call_client.js index ec261d65dd6fa..bdaef283f2d35 100644 --- a/src/legacy/ui/public/courier/fetch/__tests__/call_client.js +++ b/src/legacy/ui/public/courier/fetch/__tests__/call_client.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import NoDigestPromises from 'test_utils/no_digest_promises'; import { delay } from 'bluebird'; diff --git a/src/legacy/ui/public/courier/fetch/__tests__/fetch_now.js b/src/legacy/ui/public/courier/fetch/__tests__/fetch_now.js index 079a7893785f0..19032ce1f4ca3 100644 --- a/src/legacy/ui/public/courier/fetch/__tests__/fetch_now.js +++ b/src/legacy/ui/public/courier/fetch/__tests__/fetch_now.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { CallClientProvider } from '../call_client'; diff --git a/src/legacy/ui/public/courier/fetch/request/search_request/__tests__/search_request.js b/src/legacy/ui/public/courier/fetch/request/search_request/__tests__/search_request.js index aeddc6e065455..ecac8cd474098 100644 --- a/src/legacy/ui/public/courier/fetch/request/search_request/__tests__/search_request.js +++ b/src/legacy/ui/public/courier/fetch/request/search_request/__tests__/search_request.js @@ -19,7 +19,7 @@ import ngMock from 'ng_mock'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SearchRequestProvider } from '../search_request'; import { searchRequestQueue } from '../../../../search_request_queue'; diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js index 714bbb340969d..80f0ce3309a41 100644 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js +++ b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source'; diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js index b1cc13d057f90..6914e9338028c 100644 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js +++ b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { times } from 'lodash'; import sinon from 'sinon'; diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js index b875e57e5d3cf..33b8140b746f5 100644 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js +++ b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { SegmentedSearchRequestProvider } from '../segmented_search_request'; diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js index b882b3ae5fedf..7b499fbd87e0e 100644 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js +++ b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import HitSortFnProv from 'plugins/kibana/discover/_hit_sort_fn'; import NoDigestPromises from 'test_utils/no_digest_promises'; diff --git a/src/legacy/ui/public/courier/fetch/request/serialize_fetch_params/__tests__/serialize_fetch_params.js b/src/legacy/ui/public/courier/fetch/request/serialize_fetch_params/__tests__/serialize_fetch_params.js index 84548e6626752..47c50d726c9fc 100644 --- a/src/legacy/ui/public/courier/fetch/request/serialize_fetch_params/__tests__/serialize_fetch_params.js +++ b/src/legacy/ui/public/courier/fetch/request/serialize_fetch_params/__tests__/serialize_fetch_params.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import StubIndexPatternProvider from 'test_utils/stub_index_pattern'; diff --git a/src/legacy/ui/public/courier/search_request_queue/__tests__/search_request_queue.js b/src/legacy/ui/public/courier/search_request_queue/__tests__/search_request_queue.js index 434894e07c21a..f6b4e4bef20c2 100644 --- a/src/legacy/ui/public/courier/search_request_queue/__tests__/search_request_queue.js +++ b/src/legacy/ui/public/courier/search_request_queue/__tests__/search_request_queue.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { searchRequestQueue } from '../search_request_queue'; diff --git a/src/legacy/ui/public/courier/search_source/__tests__/normalize_sort_request.js b/src/legacy/ui/public/courier/search_source/__tests__/normalize_sort_request.js index 810f9cf045495..2358fdb520715 100644 --- a/src/legacy/ui/public/courier/search_source/__tests__/normalize_sort_request.js +++ b/src/legacy/ui/public/courier/search_source/__tests__/normalize_sort_request.js @@ -19,7 +19,7 @@ import '../../../private'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { NormalizeSortRequestProvider } from '../_normalize_sort_request'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import _ from 'lodash'; diff --git a/src/legacy/ui/public/courier/search_source/__tests__/search_source.js b/src/legacy/ui/public/courier/search_source/__tests__/search_source.js index 2034c63e0605f..8297c751da5fe 100644 --- a/src/legacy/ui/public/courier/search_source/__tests__/search_source.js +++ b/src/legacy/ui/public/courier/search_source/__tests__/search_source.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { searchRequestQueue } from '../../search_request_queue'; diff --git a/src/legacy/ui/public/debounce/__tests__/debounce.js b/src/legacy/ui/public/debounce/__tests__/debounce.js index 5aa4233613ce1..e5138643101f5 100644 --- a/src/legacy/ui/public/debounce/__tests__/debounce.js +++ b/src/legacy/ui/public/debounce/__tests__/debounce.js @@ -19,7 +19,7 @@ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { DebounceProvider } from '..'; diff --git a/src/legacy/ui/public/directives/__tests__/css_truncate.js b/src/legacy/ui/public/directives/__tests__/css_truncate.js index 3c851a7df6842..ec46448962dc3 100644 --- a/src/legacy/ui/public/directives/__tests__/css_truncate.js +++ b/src/legacy/ui/public/directives/__tests__/css_truncate.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import 'plugins/kibana/discover/index'; diff --git a/src/legacy/ui/public/directives/__tests__/fixed_scroll.js b/src/legacy/ui/public/directives/__tests__/fixed_scroll.js index cec917cf4d1f7..651e3af550e44 100644 --- a/src/legacy/ui/public/directives/__tests__/fixed_scroll.js +++ b/src/legacy/ui/public/directives/__tests__/fixed_scroll.js @@ -18,7 +18,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../fixed_scroll'; import $ from 'jquery'; diff --git a/src/legacy/ui/public/directives/__tests__/inequality.js b/src/legacy/ui/public/directives/__tests__/inequality.js index a513520e49791..d503d406fdbff 100644 --- a/src/legacy/ui/public/directives/__tests__/inequality.js +++ b/src/legacy/ui/public/directives/__tests__/inequality.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../inequality'; diff --git a/src/legacy/ui/public/directives/__tests__/input_focus.js b/src/legacy/ui/public/directives/__tests__/input_focus.js index 9b1bbe25c844c..5336c01d74d80 100644 --- a/src/legacy/ui/public/directives/__tests__/input_focus.js +++ b/src/legacy/ui/public/directives/__tests__/input_focus.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import $ from 'jquery'; import '../input_focus'; diff --git a/src/legacy/ui/public/directives/__tests__/json_input.js b/src/legacy/ui/public/directives/__tests__/json_input.js index 43ecea162f166..b2ad6c8c47321 100644 --- a/src/legacy/ui/public/directives/__tests__/json_input.js +++ b/src/legacy/ui/public/directives/__tests__/json_input.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../json_input'; diff --git a/src/legacy/ui/public/directives/__tests__/paginated_selectable_list.js b/src/legacy/ui/public/directives/__tests__/paginated_selectable_list.js index 5246cc3568fd8..319b16c6a3233 100644 --- a/src/legacy/ui/public/directives/__tests__/paginated_selectable_list.js +++ b/src/legacy/ui/public/directives/__tests__/paginated_selectable_list.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; diff --git a/src/legacy/ui/public/directives/__tests__/parse_query.js b/src/legacy/ui/public/directives/__tests__/parse_query.js index 3239bbceae248..12d9d12053286 100644 --- a/src/legacy/ui/public/directives/__tests__/parse_query.js +++ b/src/legacy/ui/public/directives/__tests__/parse_query.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; // Load the kibana app dependencies. diff --git a/src/legacy/ui/public/directives/__tests__/truncate.js b/src/legacy/ui/public/directives/__tests__/truncate.js index 864db63805691..7cf0d2e3799b1 100644 --- a/src/legacy/ui/public/directives/__tests__/truncate.js +++ b/src/legacy/ui/public/directives/__tests__/truncate.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import 'plugins/kibana/discover/index'; diff --git a/src/legacy/ui/public/directives/__tests__/validate_json.js b/src/legacy/ui/public/directives/__tests__/validate_json.js index b59ee7bccf7ec..dd533851ac4d5 100644 --- a/src/legacy/ui/public/directives/__tests__/validate_json.js +++ b/src/legacy/ui/public/directives/__tests__/validate_json.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../validate_json'; diff --git a/src/legacy/ui/public/doc_table/__tests__/actions/filter.js b/src/legacy/ui/public/doc_table/__tests__/actions/filter.js index 4a050797f94f7..496ec7dc87396 100644 --- a/src/legacy/ui/public/doc_table/__tests__/actions/filter.js +++ b/src/legacy/ui/public/doc_table/__tests__/actions/filter.js @@ -21,7 +21,7 @@ import { addFilter } from '../../actions/filter'; import { FilterManagerProvider } from '../../../filter_manager'; import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import NoDigestPromises from 'test_utils/no_digest_promises'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; diff --git a/src/legacy/ui/public/doc_table/__tests__/doc_table.js b/src/legacy/ui/public/doc_table/__tests__/doc_table.js index 5395ddb4f216f..56cd15b66b37e 100644 --- a/src/legacy/ui/public/doc_table/__tests__/doc_table.js +++ b/src/legacy/ui/public/doc_table/__tests__/doc_table.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; import ngMock from 'ng_mock'; import '../../private'; diff --git a/src/legacy/ui/public/doc_table/__tests__/lib/get_sort.js b/src/legacy/ui/public/doc_table/__tests__/lib/get_sort.js index 3ea586f457993..bec26d38d0fa7 100644 --- a/src/legacy/ui/public/doc_table/__tests__/lib/get_sort.js +++ b/src/legacy/ui/public/doc_table/__tests__/lib/get_sort.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { getSort } from '../../lib/get_sort'; diff --git a/src/legacy/ui/public/doc_table/__tests__/lib/rows_headers.js b/src/legacy/ui/public/doc_table/__tests__/lib/rows_headers.js index 1cbe730aace39..b2660facf7a5a 100644 --- a/src/legacy/ui/public/doc_table/__tests__/lib/rows_headers.js +++ b/src/legacy/ui/public/doc_table/__tests__/lib/rows_headers.js @@ -20,7 +20,7 @@ import angular from 'angular'; import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { getFakeRow, getFakeRowVals } from 'fixtures/fake_row'; import $ from 'jquery'; diff --git a/src/legacy/ui/public/doc_title/__tests__/doc_title.js b/src/legacy/ui/public/doc_title/__tests__/doc_title.js index 4c459a17a6c69..2c0ec6766cb14 100644 --- a/src/legacy/ui/public/doc_title/__tests__/doc_title.js +++ b/src/legacy/ui/public/doc_title/__tests__/doc_title.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { DocTitleProvider } from '..'; diff --git a/src/legacy/ui/public/doc_viewer/__tests__/doc_viewer.js b/src/legacy/ui/public/doc_viewer/__tests__/doc_viewer.js index e55718374be16..b6ba1f7206a19 100644 --- a/src/legacy/ui/public/doc_viewer/__tests__/doc_viewer.js +++ b/src/legacy/ui/public/doc_viewer/__tests__/doc_viewer.js @@ -19,7 +19,7 @@ import angular from 'angular'; import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../private'; diff --git a/src/legacy/ui/public/documentation_links/__tests__/documentation_links.js b/src/legacy/ui/public/documentation_links/__tests__/documentation_links.js index 22e6d8ecfbff6..60ab7a03576c3 100644 --- a/src/legacy/ui/public/documentation_links/__tests__/documentation_links.js +++ b/src/legacy/ui/public/documentation_links/__tests__/documentation_links.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { documentationLinks } from '../documentation_links'; import { metadata } from '../../metadata'; diff --git a/src/legacy/ui/public/draggable/__tests__/draggable.js b/src/legacy/ui/public/draggable/__tests__/draggable.js index 8cba8a8ebb11c..fc0601a9b67e9 100644 --- a/src/legacy/ui/public/draggable/__tests__/draggable.js +++ b/src/legacy/ui/public/draggable/__tests__/draggable.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; let init; diff --git a/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js b/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js index 75d114e397fb8..48b92b79c0b7e 100644 --- a/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js +++ b/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { IE_REGEX } from '../url_overflow_service.js'; describe('IE_REGEX', () => { diff --git a/src/legacy/ui/public/factories/__tests__/base_object.js b/src/legacy/ui/public/factories/__tests__/base_object.js index 913f647db3360..5e94cd8fb4623 100644 --- a/src/legacy/ui/public/factories/__tests__/base_object.js +++ b/src/legacy/ui/public/factories/__tests__/base_object.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../private'; diff --git a/src/legacy/ui/public/factories/__tests__/events.js b/src/legacy/ui/public/factories/__tests__/events.js index c9ba7f5798544..38fcd642fcddb 100644 --- a/src/legacy/ui/public/factories/__tests__/events.js +++ b/src/legacy/ui/public/factories/__tests__/events.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../../private'; import { EventsProvider } from '../../events'; diff --git a/src/legacy/ui/public/fancy_forms/__tests__/fancy_forms.js b/src/legacy/ui/public/fancy_forms/__tests__/fancy_forms.js index 401255ba44d6b..4e1cbb2595c2c 100644 --- a/src/legacy/ui/public/fancy_forms/__tests__/fancy_forms.js +++ b/src/legacy/ui/public/fancy_forms/__tests__/fancy_forms.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import $ from 'jquery'; describe('fancy forms', function () { diff --git a/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js b/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js index 005e6441b03a8..1d8cda79d10f0 100644 --- a/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js +++ b/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import $ from 'jquery'; diff --git a/src/legacy/ui/public/field_wildcard/__tests__/field_wildcard.js b/src/legacy/ui/public/field_wildcard/__tests__/field_wildcard.js index 0bd5fe8e8ed77..aeffdbc8bfa6c 100644 --- a/src/legacy/ui/public/field_wildcard/__tests__/field_wildcard.js +++ b/src/legacy/ui/public/field_wildcard/__tests__/field_wildcard.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FieldWildcardProvider } from '../../field_wildcard'; diff --git a/src/legacy/ui/public/filter_bar/__tests__/_add_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_add_filters.js index faa2378ad8bf5..49fbafdf4ee92 100644 --- a/src/legacy/ui/public/filter_bar/__tests__/_add_filters.js +++ b/src/legacy/ui/public/filter_bar/__tests__/_add_filters.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import MockState from 'fixtures/mock_state'; import { FilterBarQueryFilterProvider } from '../query_filter'; diff --git a/src/legacy/ui/public/filter_bar/__tests__/_get_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_get_filters.js index 5b0abd9efcdf4..3805ce1ccaf1e 100644 --- a/src/legacy/ui/public/filter_bar/__tests__/_get_filters.js +++ b/src/legacy/ui/public/filter_bar/__tests__/_get_filters.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import MockState from 'fixtures/mock_state'; import { FilterBarQueryFilterProvider } from '../query_filter'; diff --git a/src/legacy/ui/public/filter_bar/__tests__/_invert_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_invert_filters.js index 06e6ccea2eca5..e705cf22cf7fe 100644 --- a/src/legacy/ui/public/filter_bar/__tests__/_invert_filters.js +++ b/src/legacy/ui/public/filter_bar/__tests__/_invert_filters.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import MockState from 'fixtures/mock_state'; import { FilterBarQueryFilterProvider } from '../query_filter'; diff --git a/src/legacy/ui/public/filter_bar/__tests__/_pin_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_pin_filters.js index d200cbec52c4d..2c9eb4f730ada 100644 --- a/src/legacy/ui/public/filter_bar/__tests__/_pin_filters.js +++ b/src/legacy/ui/public/filter_bar/__tests__/_pin_filters.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import MockState from 'fixtures/mock_state'; import { FilterBarQueryFilterProvider } from '../query_filter'; diff --git a/src/legacy/ui/public/filter_bar/__tests__/_remove_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_remove_filters.js index 617a56da4c03c..a723031f67c4c 100644 --- a/src/legacy/ui/public/filter_bar/__tests__/_remove_filters.js +++ b/src/legacy/ui/public/filter_bar/__tests__/_remove_filters.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import MockState from 'fixtures/mock_state'; import { FilterBarQueryFilterProvider } from '../query_filter'; diff --git a/src/legacy/ui/public/filter_bar/__tests__/_toggle_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_toggle_filters.js index 0fe5be25a12ef..d1eb26641a770 100644 --- a/src/legacy/ui/public/filter_bar/__tests__/_toggle_filters.js +++ b/src/legacy/ui/public/filter_bar/__tests__/_toggle_filters.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; import MockState from 'fixtures/mock_state'; diff --git a/src/legacy/ui/public/filter_bar/__tests__/push_filter.js b/src/legacy/ui/public/filter_bar/__tests__/push_filter.js index 7d8e38b8af7f8..81b418e5665c6 100644 --- a/src/legacy/ui/public/filter_bar/__tests__/push_filter.js +++ b/src/legacy/ui/public/filter_bar/__tests__/push_filter.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarPushFilterProvider } from '../push_filter'; describe('Filter Bar pushFilter()', function () { diff --git a/src/legacy/ui/public/filter_bar/__tests__/query_filter.js b/src/legacy/ui/public/filter_bar/__tests__/query_filter.js index e3d8a0e8b61d2..9e5d3b8973c09 100644 --- a/src/legacy/ui/public/filter_bar/__tests__/query_filter.js +++ b/src/legacy/ui/public/filter_bar/__tests__/query_filter.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import './_get_filters'; import './_add_filters'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/change_time_filter.test.js b/src/legacy/ui/public/filter_bar/lib/__tests__/change_time_filter.test.js index b9916c1f08a06..52c54a4937cc8 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/change_time_filter.test.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/change_time_filter.test.js @@ -36,7 +36,7 @@ jest.mock('ui/chrome', }, }), { virtual: true }); -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { changeTimeFilter } from '../change_time_filter'; import { timefilter } from 'ui/timefilter'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/dedup_filters.js b/src/legacy/ui/public/filter_bar/lib/__tests__/dedup_filters.js index 9b6b56f8f2c10..cbe511b326c0b 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/dedup_filters.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/dedup_filters.js @@ -18,7 +18,7 @@ */ import { dedupFilters } from '../dedup_filters'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('Filter Bar Directive', function () { describe('dedupFilters(existing, filters)', function () { diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/extract_time_filter.js b/src/legacy/ui/public/filter_bar/lib/__tests__/extract_time_filter.js index da85160ef1944..970d175526841 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/extract_time_filter.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/extract_time_filter.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibExtractTimeFilterProvider } from '../extract_time_filter'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js b/src/legacy/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js index bcf6829184787..49f70b457f996 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibGenerateMappingChainProvider } from '../generate_mapping_chain'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js index e09da2a0baed7..f979c4fd1450e 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapAndFlattenFiltersProvider } from '../map_and_flatten_filters'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_default.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_default.js index 52400ceeb2a21..e22f4639d97e1 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_default.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_default.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapDefaultProvider } from '../map_default'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_exists.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_exists.js index 8a36d5cf82af6..f0b09da6ba687 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_exists.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_exists.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapExistsProvider } from '../map_exists'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_filter.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_filter.js index e15baab9e1182..0e307e2669ac2 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_filter.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_filter.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapFilterProvider } from '../map_filter'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js index 7f71845deed95..8b0ca4715d284 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js @@ -19,7 +19,7 @@ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapFlattenAndWrapFiltersProvider } from '../map_flatten_and_wrap_filters'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js index 0a61d20f3ba35..6f9d757f4b9b8 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapGeoBoundingBoxProvider } from '../map_geo_bounding_box'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js index 9f501d68c1c9f..6b17ac5b6b691 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapGeoPolygonProvider } from '../map_geo_polygon'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_match_all.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_match_all.js index d092e6d7979c4..b12128929903b 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_match_all.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_match_all.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapMatchAllProvider } from '../map_match_all'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_missing.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_missing.js index 551898c8fbdda..005b8883be51c 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_missing.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_missing.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { FilterBarLibMapMissingProvider } from '../map_missing'; describe('Filter Bar Directive', function () { diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_phrase.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_phrase.js index 0e646088a2dfc..4a0262d93a194 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_phrase.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_phrase.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapPhraseProvider } from '../map_phrase'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_query_string.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_query_string.js index a0d7a8f5b2876..056ba8b8a7de1 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_query_string.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_query_string.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapQueryStringProvider } from '../map_query_string'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_range.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_range.js index 9ec5725be2b2c..866a692751170 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_range.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_range.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterBarLibMapRangeProvider } from '../map_range'; diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/only_disabled.js b/src/legacy/ui/public/filter_bar/lib/__tests__/only_disabled.js index 7bc9c6c58d2ed..a6f4c74a70bab 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/only_disabled.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/only_disabled.js @@ -18,7 +18,7 @@ */ import { onlyDisabled } from '../only_disabled'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('Filter Bar Directive', function () { describe('onlyDisabled()', function () { diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/uniq_filters.js b/src/legacy/ui/public/filter_bar/lib/__tests__/uniq_filters.js index e42cc71485ab5..569f03f28192b 100644 --- a/src/legacy/ui/public/filter_bar/lib/__tests__/uniq_filters.js +++ b/src/legacy/ui/public/filter_bar/lib/__tests__/uniq_filters.js @@ -18,7 +18,7 @@ */ import { uniqFilters } from '../uniq_filters'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('Filter Bar Directive', function () { describe('uniqFilter', function () { diff --git a/src/legacy/ui/public/filter_manager/__tests__/filter_manager.js b/src/legacy/ui/public/filter_manager/__tests__/filter_manager.js index 87a0ed052a1c3..f1f374e0a7c3e 100644 --- a/src/legacy/ui/public/filter_manager/__tests__/filter_manager.js +++ b/src/legacy/ui/public/filter_manager/__tests__/filter_manager.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import sinon from 'sinon'; import MockState from 'fixtures/mock_state'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { FilterManagerProvider } from '..'; import { FilterBarQueryFilterProvider } from '../../filter_bar/query_filter'; diff --git a/src/legacy/ui/public/filters/__tests__/comma_list.js b/src/legacy/ui/public/filters/__tests__/comma_list.js index ec1333b1c616f..f5b155b989ac2 100644 --- a/src/legacy/ui/public/filters/__tests__/comma_list.js +++ b/src/legacy/ui/public/filters/__tests__/comma_list.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../comma_list'; diff --git a/src/legacy/ui/public/filters/__tests__/field_type.js b/src/legacy/ui/public/filters/__tests__/field_type.js index da1b5f3537d59..0b969095eb499 100644 --- a/src/legacy/ui/public/filters/__tests__/field_type.js +++ b/src/legacy/ui/public/filters/__tests__/field_type.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; import ngMock from 'ng_mock'; import 'plugins/kibana/discover/index'; diff --git a/src/legacy/ui/public/filters/__tests__/label.js b/src/legacy/ui/public/filters/__tests__/label.js index 7f702896b58c9..1696415229749 100644 --- a/src/legacy/ui/public/filters/__tests__/label.js +++ b/src/legacy/ui/public/filters/__tests__/label.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import 'plugins/kibana/discover/index'; diff --git a/src/legacy/ui/public/filters/__tests__/moment.js b/src/legacy/ui/public/filters/__tests__/moment.js index e3550df031ee7..39d7a520851d4 100644 --- a/src/legacy/ui/public/filters/__tests__/moment.js +++ b/src/legacy/ui/public/filters/__tests__/moment.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import moment from 'moment'; import ngMock from 'ng_mock'; diff --git a/src/legacy/ui/public/filters/__tests__/prop_filter.js b/src/legacy/ui/public/filters/__tests__/prop_filter.js index 2b125c47c408b..ec60121960ecb 100644 --- a/src/legacy/ui/public/filters/__tests__/prop_filter.js +++ b/src/legacy/ui/public/filters/__tests__/prop_filter.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { propFilter } from '../_prop_filter'; describe('prop filter', function () { diff --git a/src/legacy/ui/public/filters/__tests__/rison.js b/src/legacy/ui/public/filters/__tests__/rison.js index 671ef5debc659..62accfa8118a7 100644 --- a/src/legacy/ui/public/filters/__tests__/rison.js +++ b/src/legacy/ui/public/filters/__tests__/rison.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import 'plugins/kibana/discover/index'; diff --git a/src/legacy/ui/public/filters/__tests__/short_dots.js b/src/legacy/ui/public/filters/__tests__/short_dots.js index 2d23715f7a9e2..747c2c280750e 100644 --- a/src/legacy/ui/public/filters/__tests__/short_dots.js +++ b/src/legacy/ui/public/filters/__tests__/short_dots.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import 'plugins/kibana/discover/index'; import '../short_dots'; diff --git a/src/legacy/ui/public/filters/__tests__/start_from.js b/src/legacy/ui/public/filters/__tests__/start_from.js index 4b93042779111..389522bcbf944 100644 --- a/src/legacy/ui/public/filters/__tests__/start_from.js +++ b/src/legacy/ui/public/filters/__tests__/start_from.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../start_from'; diff --git a/src/legacy/ui/public/filters/__tests__/uriescape.js b/src/legacy/ui/public/filters/__tests__/uriescape.js index 2e9e14d3b0783..49a7034593821 100644 --- a/src/legacy/ui/public/filters/__tests__/uriescape.js +++ b/src/legacy/ui/public/filters/__tests__/uriescape.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import 'plugins/kibana/discover/index'; diff --git a/src/legacy/ui/public/index_patterns/__tests__/_get_computed_fields.js b/src/legacy/ui/public/index_patterns/__tests__/_get_computed_fields.js index 101032413cc2d..3d5fd961c9b51 100644 --- a/src/legacy/ui/public/index_patterns/__tests__/_get_computed_fields.js +++ b/src/legacy/ui/public/index_patterns/__tests__/_get_computed_fields.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { getComputedFields } from '../_get_computed_fields'; diff --git a/src/legacy/ui/public/index_patterns/__tests__/_index_pattern.js b/src/legacy/ui/public/index_patterns/__tests__/_index_pattern.js index 023e61bdf8a01..bf1234e95f9fc 100644 --- a/src/legacy/ui/public/index_patterns/__tests__/_index_pattern.js +++ b/src/legacy/ui/public/index_patterns/__tests__/_index_pattern.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import sinon from 'sinon'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Promise from 'bluebird'; import { DuplicateField } from '../../errors'; import { IndexedArray } from '../../indexed_array'; diff --git a/src/legacy/ui/public/index_patterns/__tests__/flatten_hit.js b/src/legacy/ui/public/index_patterns/__tests__/flatten_hit.js index 5615edad3453a..6470c0ae04749 100644 --- a/src/legacy/ui/public/index_patterns/__tests__/flatten_hit.js +++ b/src/legacy/ui/public/index_patterns/__tests__/flatten_hit.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { IndexPatternsFlattenHitProvider } from '../_flatten_hit'; diff --git a/src/legacy/ui/public/index_patterns/__tests__/index_patterns.js b/src/legacy/ui/public/index_patterns/__tests__/index_patterns.js index 6b32674b5e3ea..5a6cf3ba51c67 100644 --- a/src/legacy/ui/public/index_patterns/__tests__/index_patterns.js +++ b/src/legacy/ui/public/index_patterns/__tests__/index_patterns.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { IndexPatternProvider } from '../_index_pattern'; import { IndexPatternsProvider } from '../index_patterns'; diff --git a/src/legacy/ui/public/index_patterns/__tests__/intervals.js b/src/legacy/ui/public/index_patterns/__tests__/intervals.js index 07e4ec81e2097..cc2ba5d5f4745 100644 --- a/src/legacy/ui/public/index_patterns/__tests__/intervals.js +++ b/src/legacy/ui/public/index_patterns/__tests__/intervals.js @@ -18,7 +18,7 @@ */ import moment from 'moment'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { IndexPatternsIntervalsProvider } from '../_intervals'; diff --git a/src/legacy/ui/public/index_patterns/__tests__/unsupported_time_patterns.js b/src/legacy/ui/public/index_patterns/__tests__/unsupported_time_patterns.js index 1a6c472593712..a3af1332136a8 100644 --- a/src/legacy/ui/public/index_patterns/__tests__/unsupported_time_patterns.js +++ b/src/legacy/ui/public/index_patterns/__tests__/unsupported_time_patterns.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Chance from 'chance'; import { Storage } from '../../storage'; diff --git a/src/legacy/ui/public/index_patterns/static_utils/__tests__/index.js b/src/legacy/ui/public/index_patterns/static_utils/__tests__/index.js index e825df5d294ca..04503be6f7f78 100644 --- a/src/legacy/ui/public/index_patterns/static_utils/__tests__/index.js +++ b/src/legacy/ui/public/index_patterns/static_utils/__tests__/index.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isFilterable } from '../index'; const mockField = { diff --git a/src/legacy/ui/public/indexed_array/__tests__/indexed_array.js b/src/legacy/ui/public/indexed_array/__tests__/indexed_array.js index 66966fe095198..ccce39cdfa4d1 100644 --- a/src/legacy/ui/public/indexed_array/__tests__/indexed_array.js +++ b/src/legacy/ui/public/indexed_array/__tests__/indexed_array.js @@ -19,7 +19,7 @@ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { IndexedArray } from '..'; // this is generally a data-structure that IndexedArray is good for managing diff --git a/src/legacy/ui/public/indexed_array/__tests__/inflector.js b/src/legacy/ui/public/indexed_array/__tests__/inflector.js index ffdbbee361085..49ac79094e501 100644 --- a/src/legacy/ui/public/indexed_array/__tests__/inflector.js +++ b/src/legacy/ui/public/indexed_array/__tests__/inflector.js @@ -18,7 +18,7 @@ */ import { inflector } from '../inflector'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('IndexedArray Inflector', function () { it('returns a function', function () { diff --git a/src/legacy/ui/public/jquery/__tests__/find_test_subject.js b/src/legacy/ui/public/jquery/__tests__/find_test_subject.js index 96cda4a550ef6..6fc781fcabc5d 100644 --- a/src/legacy/ui/public/jquery/__tests__/find_test_subject.js +++ b/src/legacy/ui/public/jquery/__tests__/find_test_subject.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import $ from 'jquery'; function $make(subject) { diff --git a/src/legacy/ui/public/kbn_top_nav/__tests__/kbn_top_nav.js b/src/legacy/ui/public/kbn_top_nav/__tests__/kbn_top_nav.js index 953e903bb414d..6aff951f581e5 100644 --- a/src/legacy/ui/public/kbn_top_nav/__tests__/kbn_top_nav.js +++ b/src/legacy/ui/public/kbn_top_nav/__tests__/kbn_top_nav.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { assign, pluck } from 'lodash'; import $ from 'jquery'; diff --git a/src/legacy/ui/public/kbn_top_nav/__tests__/kbn_top_nav_controller.js b/src/legacy/ui/public/kbn_top_nav/__tests__/kbn_top_nav_controller.js index ec1a82349eed5..e0ad7ecceb9ca 100644 --- a/src/legacy/ui/public/kbn_top_nav/__tests__/kbn_top_nav_controller.js +++ b/src/legacy/ui/public/kbn_top_nav/__tests__/kbn_top_nav_controller.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { pluck } from 'lodash'; import sinon from 'sinon'; import { KbnTopNavControllerProvider } from '../kbn_top_nav_controller'; diff --git a/src/legacy/ui/public/listen/__tests__/listen.js b/src/legacy/ui/public/listen/__tests__/listen.js index a82c791016ee3..84838549b2a34 100644 --- a/src/legacy/ui/public/listen/__tests__/listen.js +++ b/src/legacy/ui/public/listen/__tests__/listen.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '..'; import { EventsProvider } from '../../events'; diff --git a/src/legacy/ui/public/management/__tests__/index.js b/src/legacy/ui/public/management/__tests__/index.js index 1fbfe74bb7963..6c794b3c189f0 100644 --- a/src/legacy/ui/public/management/__tests__/index.js +++ b/src/legacy/ui/public/management/__tests__/index.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { management } from '..'; import { ManagementSection } from '../section'; diff --git a/src/legacy/ui/public/management/__tests__/section.js b/src/legacy/ui/public/management/__tests__/section.js index 4f21b0b2caa59..cc49d346213d6 100644 --- a/src/legacy/ui/public/management/__tests__/section.js +++ b/src/legacy/ui/public/management/__tests__/section.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ManagementSection } from '../section'; import { IndexedArray } from '../../indexed_array'; diff --git a/src/legacy/ui/public/modals/__tests__/confirm_modal.js b/src/legacy/ui/public/modals/__tests__/confirm_modal.js index c700e6bf2b8a5..83b0155607f21 100644 --- a/src/legacy/ui/public/modals/__tests__/confirm_modal.js +++ b/src/legacy/ui/public/modals/__tests__/confirm_modal.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; import _ from 'lodash'; diff --git a/src/legacy/ui/public/modals/__tests__/confirm_modal_promise.js b/src/legacy/ui/public/modals/__tests__/confirm_modal_promise.js index 016617b80bf31..f5fabfd5e93a5 100644 --- a/src/legacy/ui/public/modals/__tests__/confirm_modal_promise.js +++ b/src/legacy/ui/public/modals/__tests__/confirm_modal_promise.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; import $ from 'jquery'; diff --git a/src/legacy/ui/public/notify/__tests__/notifier.js b/src/legacy/ui/public/notify/__tests__/notifier.js index 6e4b101e59f6d..f12a1e917cc0c 100644 --- a/src/legacy/ui/public/notify/__tests__/notifier.js +++ b/src/legacy/ui/public/notify/__tests__/notifier.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { Notifier } from '..'; import { metadata } from 'ui/metadata'; diff --git a/src/legacy/ui/public/notify/lib/format_es_msg.test.js b/src/legacy/ui/public/notify/lib/format_es_msg.test.js index 4df4f54f1796c..b6484a23f720c 100644 --- a/src/legacy/ui/public/notify/lib/format_es_msg.test.js +++ b/src/legacy/ui/public/notify/lib/format_es_msg.test.js @@ -18,7 +18,7 @@ */ import { formatESMsg } from './format_es_msg'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('formatESMsg', () => { test('should return undefined if passed a basic error', () => { diff --git a/src/legacy/ui/public/notify/lib/format_msg.test.js b/src/legacy/ui/public/notify/lib/format_msg.test.js index 96e532bfa54b5..d58b97455e8e9 100644 --- a/src/legacy/ui/public/notify/lib/format_msg.test.js +++ b/src/legacy/ui/public/notify/lib/format_msg.test.js @@ -18,7 +18,7 @@ */ import { formatMsg } from './format_msg'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('formatMsg', () => { test('should prepend the second argument to result', () => { diff --git a/src/legacy/ui/public/paginated_table/__tests__/index.js b/src/legacy/ui/public/paginated_table/__tests__/index.js index 2a8ab16b6b0f8..dcaed42464036 100644 --- a/src/legacy/ui/public/paginated_table/__tests__/index.js +++ b/src/legacy/ui/public/paginated_table/__tests__/index.js @@ -19,7 +19,7 @@ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '..'; import $ from 'jquery'; diff --git a/src/legacy/ui/public/persisted_state/__tests__/persisted_state_provider.js b/src/legacy/ui/public/persisted_state/__tests__/persisted_state_provider.js index 420fc5dff4fb6..7300bd159337c 100644 --- a/src/legacy/ui/public/persisted_state/__tests__/persisted_state_provider.js +++ b/src/legacy/ui/public/persisted_state/__tests__/persisted_state_provider.js @@ -21,7 +21,7 @@ import _ from 'lodash'; import sinon from 'sinon'; import noDigestPromises from 'test_utils/no_digest_promises'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PersistedStateError } from '../../errors'; import '..'; diff --git a/src/legacy/ui/public/private/__tests__/private.js b/src/legacy/ui/public/private/__tests__/private.js index 297016d77ad16..d0859bb00bade 100644 --- a/src/legacy/ui/public/private/__tests__/private.js +++ b/src/legacy/ui/public/private/__tests__/private.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; describe('Private module loader', function () { diff --git a/src/legacy/ui/public/promises/__tests__/promises.js b/src/legacy/ui/public/promises/__tests__/promises.js index b0f6971784b4e..85c5835637b8e 100644 --- a/src/legacy/ui/public/promises/__tests__/promises.js +++ b/src/legacy/ui/public/promises/__tests__/promises.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; diff --git a/src/legacy/ui/public/registry/__tests__/registry.js b/src/legacy/ui/public/registry/__tests__/registry.js index e6bcaa3e94b0f..56a19814058c1 100644 --- a/src/legacy/ui/public/registry/__tests__/registry.js +++ b/src/legacy/ui/public/registry/__tests__/registry.js @@ -18,7 +18,7 @@ */ import { uiRegistry } from '../_registry'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; describe('Registry', function () { diff --git a/src/legacy/ui/public/render_directive/__tests__/render_directive.js b/src/legacy/ui/public/render_directive/__tests__/render_directive.js index bea391e95469c..ff7225271e301 100644 --- a/src/legacy/ui/public/render_directive/__tests__/render_directive.js +++ b/src/legacy/ui/public/render_directive/__tests__/render_directive.js @@ -19,7 +19,7 @@ import angular from 'angular'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '..'; diff --git a/src/legacy/ui/public/resize_checker/__tests__/resize_checker.js b/src/legacy/ui/public/resize_checker/__tests__/resize_checker.js index 50533ac3fb248..5fccf77f8f13d 100644 --- a/src/legacy/ui/public/resize_checker/__tests__/resize_checker.js +++ b/src/legacy/ui/public/resize_checker/__tests__/resize_checker.js @@ -19,7 +19,7 @@ import $ from 'jquery'; import { delay } from 'bluebird'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import ngMock from 'ng_mock'; diff --git a/src/legacy/ui/public/routes/__tests__/_route_manager.js b/src/legacy/ui/public/routes/__tests__/_route_manager.js index 40a8a779ccb75..d6d4c869b4b7e 100644 --- a/src/legacy/ui/public/routes/__tests__/_route_manager.js +++ b/src/legacy/ui/public/routes/__tests__/_route_manager.js @@ -21,7 +21,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; import sinon from 'sinon'; import RouteManager from '../route_manager'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; let routes; // will contain an new instance of RouteManager for each test const chainableMethods = [ diff --git a/src/legacy/ui/public/routes/__tests__/_work_queue.js b/src/legacy/ui/public/routes/__tests__/_work_queue.js index bdbda577718be..f5ecebd8e596b 100644 --- a/src/legacy/ui/public/routes/__tests__/_work_queue.js +++ b/src/legacy/ui/public/routes/__tests__/_work_queue.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { WorkQueue } from '../work_queue'; import sinon from 'sinon'; diff --git a/src/legacy/ui/public/routes/__tests__/_wrap_route_with_prep.js b/src/legacy/ui/public/routes/__tests__/_wrap_route_with_prep.js index aac016082ade3..44b99a72b402c 100644 --- a/src/legacy/ui/public/routes/__tests__/_wrap_route_with_prep.js +++ b/src/legacy/ui/public/routes/__tests__/_wrap_route_with_prep.js @@ -18,7 +18,7 @@ */ import RouteManager from '../route_manager'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; diff --git a/src/legacy/ui/public/saved_objects/__tests__/find_object_by_title.js b/src/legacy/ui/public/saved_objects/__tests__/find_object_by_title.js index 7df77b43adde1..6539f8c034136 100644 --- a/src/legacy/ui/public/saved_objects/__tests__/find_object_by_title.js +++ b/src/legacy/ui/public/saved_objects/__tests__/find_object_by_title.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { findObjectByTitle } from '../find_object_by_title'; import { SimpleSavedObject } from '../simple_saved_object'; diff --git a/src/legacy/ui/public/saved_objects/__tests__/saved_object.js b/src/legacy/ui/public/saved_objects/__tests__/saved_object.js index 7cfa41b301198..c7f3a3da6259d 100644 --- a/src/legacy/ui/public/saved_objects/__tests__/saved_object.js +++ b/src/legacy/ui/public/saved_objects/__tests__/saved_object.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import BluebirdPromise from 'bluebird'; diff --git a/src/legacy/ui/public/saved_objects/__tests__/simple_saved_object.js b/src/legacy/ui/public/saved_objects/__tests__/simple_saved_object.js index 5fe05690c0859..a6583b97972ab 100644 --- a/src/legacy/ui/public/saved_objects/__tests__/simple_saved_object.js +++ b/src/legacy/ui/public/saved_objects/__tests__/simple_saved_object.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SimpleSavedObject } from '../simple_saved_object'; describe('SimpleSavedObject', () => { diff --git a/src/legacy/ui/public/share/lib/url_shortener.test.js b/src/legacy/ui/public/share/lib/url_shortener.test.js index 0c45220ff78d1..859873bd4989f 100644 --- a/src/legacy/ui/public/share/lib/url_shortener.test.js +++ b/src/legacy/ui/public/share/lib/url_shortener.test.js @@ -21,7 +21,7 @@ jest.mock('ui/kfetch', () => ({})); jest.mock('../../chrome', () => ({})); import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { shortenUrl } from './url_shortener'; describe('Url shortener', () => { diff --git a/src/legacy/ui/public/state_management/__tests__/app_state.js b/src/legacy/ui/public/state_management/__tests__/app_state.js index 9cc80b77b93a1..6f59ba744a135 100644 --- a/src/legacy/ui/public/state_management/__tests__/app_state.js +++ b/src/legacy/ui/public/state_management/__tests__/app_state.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { AppStateProvider } from '../app_state'; diff --git a/src/legacy/ui/public/state_management/__tests__/config_provider.js b/src/legacy/ui/public/state_management/__tests__/config_provider.js index 13171e08909d4..c16300cb7aa32 100644 --- a/src/legacy/ui/public/state_management/__tests__/config_provider.js +++ b/src/legacy/ui/public/state_management/__tests__/config_provider.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../config_provider'; diff --git a/src/legacy/ui/public/state_management/__tests__/global_state.js b/src/legacy/ui/public/state_management/__tests__/global_state.js index 76d0e0c2c2826..10b127aa1b80d 100644 --- a/src/legacy/ui/public/state_management/__tests__/global_state.js +++ b/src/legacy/ui/public/state_management/__tests__/global_state.js @@ -18,7 +18,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../global_state'; diff --git a/src/legacy/ui/public/state_management/__tests__/state.js b/src/legacy/ui/public/state_management/__tests__/state.js index 95e275471a1f7..cbeb5e3650a16 100644 --- a/src/legacy/ui/public/state_management/__tests__/state.js +++ b/src/legacy/ui/public/state_management/__tests__/state.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { encode as encodeRison } from 'rison-node'; import '../../private'; diff --git a/src/legacy/ui/public/state_management/__tests__/state_monitor_factory.js b/src/legacy/ui/public/state_management/__tests__/state_monitor_factory.js index 581625f463056..75dd5024708af 100644 --- a/src/legacy/ui/public/state_management/__tests__/state_monitor_factory.js +++ b/src/legacy/ui/public/state_management/__tests__/state_monitor_factory.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { cloneDeep } from 'lodash'; import { stateMonitorFactory } from '../state_monitor_factory'; diff --git a/src/legacy/ui/public/state_management/state_hashing/__tests__/hash_url.js b/src/legacy/ui/public/state_management/state_hashing/__tests__/hash_url.js index 79641f3cf3c57..1d5b88a22d9c6 100644 --- a/src/legacy/ui/public/state_management/state_hashing/__tests__/hash_url.js +++ b/src/legacy/ui/public/state_management/state_hashing/__tests__/hash_url.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; import { parse as parseUrl } from 'url'; diff --git a/src/legacy/ui/public/state_management/state_hashing/__tests__/unhash_url.js b/src/legacy/ui/public/state_management/state_hashing/__tests__/unhash_url.js index 7a3cb67e0d735..671194ecb50f5 100644 --- a/src/legacy/ui/public/state_management/state_hashing/__tests__/unhash_url.js +++ b/src/legacy/ui/public/state_management/state_hashing/__tests__/unhash_url.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; diff --git a/src/legacy/ui/public/state_management/state_storage/__tests__/hashed_item_store.js b/src/legacy/ui/public/state_management/state_storage/__tests__/hashed_item_store.js index 15d6e4e5c040f..dfb726ce53299 100644 --- a/src/legacy/ui/public/state_management/state_storage/__tests__/hashed_item_store.js +++ b/src/legacy/ui/public/state_management/state_storage/__tests__/hashed_item_store.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; diff --git a/src/legacy/ui/public/state_management/state_storage/__tests__/state_hash.js b/src/legacy/ui/public/state_management/state_storage/__tests__/state_hash.js index 09f875a18e696..71fcf33274fc6 100644 --- a/src/legacy/ui/public/state_management/state_storage/__tests__/state_hash.js +++ b/src/legacy/ui/public/state_management/state_storage/__tests__/state_hash.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { encode as encodeRison } from 'rison-node'; import { diff --git a/src/legacy/ui/public/storage/__tests__/storage.js b/src/legacy/ui/public/storage/__tests__/storage.js index 51ef371b736d4..2f72fff129ef0 100644 --- a/src/legacy/ui/public/storage/__tests__/storage.js +++ b/src/legacy/ui/public/storage/__tests__/storage.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '..'; diff --git a/src/legacy/ui/public/style_compile/__tests__/style_compile.js b/src/legacy/ui/public/style_compile/__tests__/style_compile.js index e141b9fbb1a20..75700259d7bc5 100644 --- a/src/legacy/ui/public/style_compile/__tests__/style_compile.js +++ b/src/legacy/ui/public/style_compile/__tests__/style_compile.js @@ -18,7 +18,7 @@ */ import $ from 'jquery'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; describe('styleCompile directive', function () { diff --git a/src/legacy/ui/public/system_api/__tests__/system_api.js b/src/legacy/ui/public/system_api/__tests__/system_api.js index 45a1cd6449684..2e44bac2eef53 100644 --- a/src/legacy/ui/public/system_api/__tests__/system_api.js +++ b/src/legacy/ui/public/system_api/__tests__/system_api.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { addSystemApiHeader, isSystemApiRequest } from '../system_api'; describe('system_api', () => { diff --git a/src/legacy/ui/public/timefilter/get_time.test.ts b/src/legacy/ui/public/timefilter/get_time.test.ts index 42f89335338de..582ecae82a587 100644 --- a/src/legacy/ui/public/timefilter/get_time.test.ts +++ b/src/legacy/ui/public/timefilter/get_time.test.ts @@ -18,7 +18,7 @@ */ // @ts-ignore -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import sinon from 'sinon'; import { Filter, getTime } from './get_time'; diff --git a/src/legacy/ui/public/timefilter/lib/diff_time_picker_vals.test.js b/src/legacy/ui/public/timefilter/lib/diff_time_picker_vals.test.js index e441c351d735b..12d729dd0136b 100644 --- a/src/legacy/ui/public/timefilter/lib/diff_time_picker_vals.test.js +++ b/src/legacy/ui/public/timefilter/lib/diff_time_picker_vals.test.js @@ -19,7 +19,7 @@ import moment from 'moment'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { areTimePickerValsDifferent } from './diff_time_picker_vals'; describe('Diff Time Picker Values', () => { diff --git a/src/legacy/ui/public/timefilter/timefilter.test.js b/src/legacy/ui/public/timefilter/timefilter.test.js index eb07711126e48..c1431782baaf2 100644 --- a/src/legacy/ui/public/timefilter/timefilter.test.js +++ b/src/legacy/ui/public/timefilter/timefilter.test.js @@ -47,7 +47,7 @@ jest.mock('ui/timefilter/lib/parse_querystring', }), { virtual: true }); import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { timefilter } from './timefilter'; diff --git a/src/legacy/ui/public/url/__tests__/extract_app_path_and_id.js b/src/legacy/ui/public/url/__tests__/extract_app_path_and_id.js index 1df0b14d5d4ad..9c2b79705456e 100644 --- a/src/legacy/ui/public/url/__tests__/extract_app_path_and_id.js +++ b/src/legacy/ui/public/url/__tests__/extract_app_path_and_id.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { extractAppPathAndId } from '../extract_app_path_and_id'; diff --git a/src/legacy/ui/public/url/__tests__/kibana_parsed_url.js b/src/legacy/ui/public/url/__tests__/kibana_parsed_url.js index cbca2c6aff001..5dd005480e5b5 100644 --- a/src/legacy/ui/public/url/__tests__/kibana_parsed_url.js +++ b/src/legacy/ui/public/url/__tests__/kibana_parsed_url.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { KibanaParsedUrl } from '../kibana_parsed_url'; diff --git a/src/legacy/ui/public/url/__tests__/prepend_path.js b/src/legacy/ui/public/url/__tests__/prepend_path.js index 1ab4698ffd5de..b31449322a024 100644 --- a/src/legacy/ui/public/url/__tests__/prepend_path.js +++ b/src/legacy/ui/public/url/__tests__/prepend_path.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { prependPath } from '../prepend_path'; diff --git a/src/legacy/ui/public/url/__tests__/url.js b/src/legacy/ui/public/url/__tests__/url.js index 7f779d594669c..52af742492aed 100644 --- a/src/legacy/ui/public/url/__tests__/url.js +++ b/src/legacy/ui/public/url/__tests__/url.js @@ -19,7 +19,7 @@ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import faker from 'faker'; import _ from 'lodash'; diff --git a/src/legacy/ui/public/utils/__tests__/brush_event.test.js b/src/legacy/ui/public/utils/__tests__/brush_event.test.js index 6b27dd79eedc4..c7c1804cde780 100644 --- a/src/legacy/ui/public/utils/__tests__/brush_event.test.js +++ b/src/legacy/ui/public/utils/__tests__/brush_event.test.js @@ -38,7 +38,7 @@ jest.mock('ui/chrome', import _ from 'lodash'; import moment from 'moment'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { onBrushEvent } from '../brush_event'; import { timefilter } from 'ui/timefilter'; diff --git a/src/legacy/ui/public/utils/__tests__/cidr_mask.ts b/src/legacy/ui/public/utils/__tests__/cidr_mask.ts index 8624bb1b6e0b2..5343328e55786 100644 --- a/src/legacy/ui/public/utils/__tests__/cidr_mask.ts +++ b/src/legacy/ui/public/utils/__tests__/cidr_mask.ts @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { CidrMask } from '../cidr_mask'; describe('CidrMask', () => { diff --git a/src/legacy/ui/public/utils/__tests__/collection.js b/src/legacy/ui/public/utils/__tests__/collection.js index a733b8b2433bc..978c6e75cece7 100644 --- a/src/legacy/ui/public/utils/__tests__/collection.js +++ b/src/legacy/ui/public/utils/__tests__/collection.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { groupBy } from 'lodash'; import { move, pushAll, organizeBy } from '../collection'; diff --git a/src/legacy/ui/public/utils/__tests__/decode_geo_hash.js b/src/legacy/ui/public/utils/__tests__/decode_geo_hash.js index 5b09a0cc8b4cd..5a0a447e345c4 100644 --- a/src/legacy/ui/public/utils/__tests__/decode_geo_hash.js +++ b/src/legacy/ui/public/utils/__tests__/decode_geo_hash.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { geohashColumns } from '../decode_geo_hash'; describe('decode_geo_hash', function () { diff --git a/src/legacy/ui/public/utils/__tests__/diff_object.js b/src/legacy/ui/public/utils/__tests__/diff_object.js index 919dfdfcbc9ee..cc9463c163d4b 100644 --- a/src/legacy/ui/public/utils/__tests__/diff_object.js +++ b/src/legacy/ui/public/utils/__tests__/diff_object.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; import { applyDiff } from '../diff_object'; diff --git a/src/legacy/ui/public/utils/__tests__/ipv4_address.ts b/src/legacy/ui/public/utils/__tests__/ipv4_address.ts index 5e967da189e87..ad4efec6f1e52 100644 --- a/src/legacy/ui/public/utils/__tests__/ipv4_address.ts +++ b/src/legacy/ui/public/utils/__tests__/ipv4_address.ts @@ -17,7 +17,7 @@ * under the License. */ // @ts-ignore -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Ipv4Address from '../ipv4_address'; describe('Ipv4Address', () => { diff --git a/src/legacy/ui/public/utils/__tests__/mapping_setup.js b/src/legacy/ui/public/utils/__tests__/mapping_setup.js index 48dd210b9af4f..944dfaa35ed82 100644 --- a/src/legacy/ui/public/utils/__tests__/mapping_setup.js +++ b/src/legacy/ui/public/utils/__tests__/mapping_setup.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import UtilsMappingSetupProvider from '../mapping_setup'; let mappingSetup; diff --git a/src/legacy/ui/public/utils/__tests__/obj_define.js b/src/legacy/ui/public/utils/__tests__/obj_define.js index 64a699ad3c68e..5e89ba03530af 100644 --- a/src/legacy/ui/public/utils/__tests__/obj_define.js +++ b/src/legacy/ui/public/utils/__tests__/obj_define.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ObjDefine } from '../obj_define'; describe('ObjDefine Utility', function () { diff --git a/src/legacy/ui/public/utils/__tests__/ordinal_suffix.js b/src/legacy/ui/public/utils/__tests__/ordinal_suffix.js index bde297a456fff..dae12d41cfb5b 100644 --- a/src/legacy/ui/public/utils/__tests__/ordinal_suffix.js +++ b/src/legacy/ui/public/utils/__tests__/ordinal_suffix.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import { ordinalSuffix } from '../ordinal_suffix'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ordinal suffix util', function () { const checks = { diff --git a/src/legacy/ui/public/utils/__tests__/parse_interval.js b/src/legacy/ui/public/utils/__tests__/parse_interval.js index b068ce170e128..bce134be4336d 100644 --- a/src/legacy/ui/public/utils/__tests__/parse_interval.js +++ b/src/legacy/ui/public/utils/__tests__/parse_interval.js @@ -18,7 +18,7 @@ */ import { parseInterval } from '../parse_interval'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('parseInterval', function () { it('should correctly parse an interval containing unit and value', function () { diff --git a/src/legacy/ui/public/utils/__tests__/range.js b/src/legacy/ui/public/utils/__tests__/range.js index e6421c3101753..e7947894d3e22 100644 --- a/src/legacy/ui/public/utils/__tests__/range.js +++ b/src/legacy/ui/public/utils/__tests__/range.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { parseRange } from '../range'; describe('Range parsing utility', function () { diff --git a/src/legacy/ui/public/utils/__tests__/simple_emitter.js b/src/legacy/ui/public/utils/__tests__/simple_emitter.js index 6dbacbe4adfe9..25224a409f8f4 100644 --- a/src/legacy/ui/public/utils/__tests__/simple_emitter.js +++ b/src/legacy/ui/public/utils/__tests__/simple_emitter.js @@ -18,7 +18,7 @@ */ import { SimpleEmitter } from '../simple_emitter'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; describe('SimpleEmitter class', function () { diff --git a/src/legacy/ui/public/utils/__tests__/sort_prefix_first.js b/src/legacy/ui/public/utils/__tests__/sort_prefix_first.js index e820ffff5aa3c..016e13b372c3d 100644 --- a/src/legacy/ui/public/utils/__tests__/sort_prefix_first.js +++ b/src/legacy/ui/public/utils/__tests__/sort_prefix_first.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { sortPrefixFirst } from '../sort_prefix_first'; describe('sortPrefixFirst', function () { diff --git a/src/legacy/ui/public/vis/__tests__/_agg_config.js b/src/legacy/ui/public/vis/__tests__/_agg_config.js index 707ccf2d6f17a..1929b4312e14f 100644 --- a/src/legacy/ui/public/vis/__tests__/_agg_config.js +++ b/src/legacy/ui/public/vis/__tests__/_agg_config.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VisProvider } from '..'; import { AggType } from '../../agg_types/agg_type'; diff --git a/src/legacy/ui/public/vis/__tests__/_agg_config_result.js b/src/legacy/ui/public/vis/__tests__/_agg_config_result.js index 22254dc36d7f8..988c4dc872152 100644 --- a/src/legacy/ui/public/vis/__tests__/_agg_config_result.js +++ b/src/legacy/ui/public/vis/__tests__/_agg_config_result.js @@ -18,7 +18,7 @@ */ import AggConfigResult from '../agg_config_result'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VisProvider } from '..'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/vis/__tests__/_agg_configs.js b/src/legacy/ui/public/vis/__tests__/_agg_configs.js index 4ae10aed6a53e..2c663800a4d28 100644 --- a/src/legacy/ui/public/vis/__tests__/_agg_configs.js +++ b/src/legacy/ui/public/vis/__tests__/_agg_configs.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { AggConfig } from '../agg_config'; import { VisProvider } from '..'; diff --git a/src/legacy/ui/public/vis/__tests__/_vis.js b/src/legacy/ui/public/vis/__tests__/_vis.js index ed1c767137a88..5c162bd45ace2 100644 --- a/src/legacy/ui/public/vis/__tests__/_vis.js +++ b/src/legacy/ui/public/vis/__tests__/_vis.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VisProvider } from '..'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { VisTypesRegistryProvider } from '../../registry/vis_types'; diff --git a/src/legacy/ui/public/vis/__tests__/components/color.js b/src/legacy/ui/public/vis/__tests__/components/color.js index 5eda6b12fbb50..ba8e4479d2d63 100644 --- a/src/legacy/ui/public/vis/__tests__/components/color.js +++ b/src/legacy/ui/public/vis/__tests__/components/color.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; import d3 from 'd3'; diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_client.js b/src/legacy/ui/public/vis/__tests__/map/ems_client.js index 022bb2417615d..6ac25c6f53f00 100644 --- a/src/legacy/ui/public/vis/__tests__/map/ems_client.js +++ b/src/legacy/ui/public/vis/__tests__/map/ems_client.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import EMS_CATALOGUE from './ems_mocks/sample_manifest.json'; import EMS_FILES from './ems_mocks/sample_files.json'; import EMS_TILES from './ems_mocks/sample_tiles.json'; diff --git a/src/legacy/ui/public/vis/__tests__/map/kibana_map.js b/src/legacy/ui/public/vis/__tests__/map/kibana_map.js index ed1c4e1e4b8fd..e67d4b5f7603b 100644 --- a/src/legacy/ui/public/vis/__tests__/map/kibana_map.js +++ b/src/legacy/ui/public/vis/__tests__/map/kibana_map.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { KibanaMap } from '../../map/kibana_map'; import { KibanaMapLayer } from '../../map/kibana_map_layer'; import L from 'leaflet'; diff --git a/src/legacy/ui/public/vis/__tests__/map/service_settings.js b/src/legacy/ui/public/vis/__tests__/map/service_settings.js index 51ce93a376044..20097697bd0a2 100644 --- a/src/legacy/ui/public/vis/__tests__/map/service_settings.js +++ b/src/legacy/ui/public/vis/__tests__/map/service_settings.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import url from 'url'; diff --git a/src/legacy/ui/public/vis/__tests__/response_handlers/_build_chart_data.js b/src/legacy/ui/public/vis/__tests__/response_handlers/_build_chart_data.js index 51c03d5338f44..5b1f8c7c55475 100644 --- a/src/legacy/ui/public/vis/__tests__/response_handlers/_build_chart_data.js +++ b/src/legacy/ui/public/vis/__tests__/response_handlers/_build_chart_data.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { aggResponseIndex } from '../../../agg_response'; import { VislibSeriesResponseHandlerProvider as vislibReponseHandler } from '../../response_handlers/vislib'; diff --git a/src/legacy/ui/public/vis/__tests__/response_handlers/basic.js b/src/legacy/ui/public/vis/__tests__/response_handlers/basic.js index a8281b95742b6..b80cf4abc02dd 100644 --- a/src/legacy/ui/public/vis/__tests__/response_handlers/basic.js +++ b/src/legacy/ui/public/vis/__tests__/response_handlers/basic.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VislibSeriesResponseHandlerProvider } from '../../response_handlers/vislib'; describe('Basic Response Handler', function () { diff --git a/src/legacy/ui/public/vis/__tests__/vis_types/base_vis_type.js b/src/legacy/ui/public/vis/__tests__/vis_types/base_vis_type.js index 2a79b40e7496a..7590ff93d2b47 100644 --- a/src/legacy/ui/public/vis/__tests__/vis_types/base_vis_type.js +++ b/src/legacy/ui/public/vis/__tests__/vis_types/base_vis_type.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { BaseVisTypeProvider } from '../../vis_types/base_vis_type'; diff --git a/src/legacy/ui/public/vis/__tests__/vis_types/react_vis_type.js b/src/legacy/ui/public/vis/__tests__/vis_types/react_vis_type.js index cf2fbab880814..99b485e8ef55d 100644 --- a/src/legacy/ui/public/vis/__tests__/vis_types/react_vis_type.js +++ b/src/legacy/ui/public/vis/__tests__/vis_types/react_vis_type.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { ReactVisTypeProvider } from '../../vis_types/react_vis_type'; diff --git a/src/legacy/ui/public/vis/__tests__/vis_types/vislib_vis_type.js b/src/legacy/ui/public/vis/__tests__/vis_types/vislib_vis_type.js index aee36e7f330da..9e6c98e94a9c4 100644 --- a/src/legacy/ui/public/vis/__tests__/vis_types/vislib_vis_type.js +++ b/src/legacy/ui/public/vis/__tests__/vis_types/vislib_vis_type.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VislibVisTypeProvider } from '../../vis_types/vislib_vis_type'; describe('Vislib Vis Type', function () { diff --git a/src/legacy/ui/public/vis/components/tooltip/__tests__/positioning.js b/src/legacy/ui/public/vis/components/tooltip/__tests__/positioning.js index c5568ec833d70..b72e947fee6cd 100644 --- a/src/legacy/ui/public/vis/components/tooltip/__tests__/positioning.js +++ b/src/legacy/ui/public/vis/components/tooltip/__tests__/positioning.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import $ from 'jquery'; import _ from 'lodash'; import sinon from 'sinon'; diff --git a/src/legacy/ui/public/vis/editors/default/__tests__/agg.js b/src/legacy/ui/public/vis/editors/default/__tests__/agg.js index 0f5c76f2f428f..c38ba179f3a5a 100644 --- a/src/legacy/ui/public/vis/editors/default/__tests__/agg.js +++ b/src/legacy/ui/public/vis/editors/default/__tests__/agg.js @@ -20,7 +20,7 @@ import angular from 'angular'; import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../agg'; diff --git a/src/legacy/ui/public/vis/editors/default/__tests__/agg_params.js b/src/legacy/ui/public/vis/editors/default/__tests__/agg_params.js index 3538b1ab5ae70..4f3c78e1469d9 100644 --- a/src/legacy/ui/public/vis/editors/default/__tests__/agg_params.js +++ b/src/legacy/ui/public/vis/editors/default/__tests__/agg_params.js @@ -20,7 +20,7 @@ import angular from 'angular'; import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import '../agg_params'; import { VisProvider } from '../../..'; diff --git a/src/legacy/ui/public/vis/editors/default/__tests__/keyboard_move.js b/src/legacy/ui/public/vis/editors/default/__tests__/keyboard_move.js index 6daf8a8d41ec0..b24e2918ac07d 100644 --- a/src/legacy/ui/public/vis/editors/default/__tests__/keyboard_move.js +++ b/src/legacy/ui/public/vis/editors/default/__tests__/keyboard_move.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; import { Direction } from '../keyboard_move'; diff --git a/src/legacy/ui/public/vis/vis_types/__tests__/vislib_vis_legend.js b/src/legacy/ui/public/vis/vis_types/__tests__/vislib_vis_legend.js index ab7bf8fab0abb..d539693a1209e 100644 --- a/src/legacy/ui/public/vis/vis_types/__tests__/vislib_vis_legend.js +++ b/src/legacy/ui/public/vis/vis_types/__tests__/vislib_vis_legend.js @@ -19,7 +19,7 @@ import $ from 'jquery'; import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VisProvider } from '../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/ui/public/vislib/__tests__/components/heatmap_color.js b/src/legacy/ui/public/vislib/__tests__/components/heatmap_color.js index 8260b97dcc2f1..d4e2a168fdf29 100644 --- a/src/legacy/ui/public/vislib/__tests__/components/heatmap_color.js +++ b/src/legacy/ui/public/vislib/__tests__/components/heatmap_color.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { getHeatmapColors } from '../../components/color/heatmap_color'; diff --git a/src/legacy/ui/public/vislib/__tests__/components/labels.js b/src/legacy/ui/public/vislib/__tests__/components/labels.js index e454bc1cf11b8..999937305d5ca 100644 --- a/src/legacy/ui/public/vislib/__tests__/components/labels.js +++ b/src/legacy/ui/public/vislib/__tests__/components/labels.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VislibComponentsLabelsLabelsProvider } from '../../components/labels/labels'; import { VislibComponentsLabelsDataArrayProvider } from '../../components/labels/data_array'; diff --git a/src/legacy/ui/public/vislib/__tests__/components/zero_injection.js b/src/legacy/ui/public/vislib/__tests__/components/zero_injection.js index 8cf0a2bdfa553..fb9e775ae2fe6 100644 --- a/src/legacy/ui/public/vislib/__tests__/components/zero_injection.js +++ b/src/legacy/ui/public/vislib/__tests__/components/zero_injection.js @@ -19,7 +19,7 @@ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VislibComponentsZeroInjectionInjectZerosProvider } from '../../components/zero_injection/inject_zeros'; import { VislibComponentsZeroInjectionOrderedXKeysProvider } from '../../components/zero_injection/ordered_x_keys'; diff --git a/src/legacy/ui/public/vislib/__tests__/index.js b/src/legacy/ui/public/vislib/__tests__/index.js index cfed27d817063..ed58765df5a81 100644 --- a/src/legacy/ui/public/vislib/__tests__/index.js +++ b/src/legacy/ui/public/vislib/__tests__/index.js @@ -19,7 +19,7 @@ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import VislibProvider from '..'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/axis/axis.js b/src/legacy/ui/public/vislib/__tests__/lib/axis/axis.js index 52add55f50430..954d7dee6c4b1 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/axis/axis.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/axis/axis.js @@ -20,7 +20,7 @@ import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import $ from 'jquery'; import '../../../../persisted_state'; import { VislibLibAxisProvider } from '../../../lib/axis'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/axis_title.js b/src/legacy/ui/public/vislib/__tests__/lib/axis_title.js index 0541261c089ad..9098a12d40fc6 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/axis_title.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/axis_title.js @@ -21,7 +21,7 @@ import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VislibLibAxisTitleProvider } from '../../lib/axis/axis_title'; import { VislibLibAxisConfigProvider } from '../../lib/axis/axis_config'; import { VislibVisConfigProvider } from '../../lib/vis_config'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/chart_title.js b/src/legacy/ui/public/vislib/__tests__/lib/chart_title.js index e88896d70872d..15bca14400bbc 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/chart_title.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/chart_title.js @@ -20,7 +20,7 @@ import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VislibLibChartTitleProvider } from '../../lib/chart_title'; import { VislibVisConfigProvider } from '../../lib/vis_config'; import '../../../persisted_state'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/data.js b/src/legacy/ui/public/vislib/__tests__/lib/data.js index ae6e166b62ef0..4cb47a4c5006f 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/data.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/data.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VislibLibDataProvider } from '../../lib/data'; import '../../../persisted_state'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/dispatch.js b/src/legacy/ui/public/vislib/__tests__/lib/dispatch.js index fb4794f147a15..5dc6854cf5ced 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/dispatch.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/dispatch.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import d3 from 'd3'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; // Data import data from 'fixtures/vislib/mock_data/date_histogram/_series'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/error_handler.js b/src/legacy/ui/public/vislib/__tests__/lib/error_handler.js index 804939001aa10..bb7d9eee51c28 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/error_handler.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/error_handler.js @@ -18,7 +18,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VislibLibErrorHandlerProvider } from '../../lib/_error_handler'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/handler/handler.js b/src/legacy/ui/public/vislib/__tests__/lib/handler/handler.js index 518fc9595ab8d..f40df40ed998a 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/handler/handler.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/handler/handler.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; // Data import series from 'fixtures/vislib/mock_data/date_histogram/_series'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/layout.js b/src/legacy/ui/public/vislib/__tests__/lib/layout/layout.js index 149f2e87cc302..93a6961b99aa7 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/layout/layout.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/layout/layout.js @@ -19,7 +19,7 @@ import d3 from 'd3'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; // Data import series from 'fixtures/vislib/mock_data/date_histogram/_series'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/layout_types.js b/src/legacy/ui/public/vislib/__tests__/lib/layout/layout_types.js index 8d4c80f728340..ec86a601d7b1a 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/layout/layout_types.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/layout/layout_types.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VislibLibLayoutLayoutTypesProvider } from '../../../lib/layout/layout_types'; describe('Vislib Layout Types Test Suite', function () { diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js b/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js index 185597f1ac3c1..c189232800d04 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js @@ -19,7 +19,7 @@ import d3 from 'd3'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import $ from 'jquery'; import { VislibLibLayoutSplitsColumnChartChartSplitProvider } from '../../../../../lib/layout/splits/column_chart/chart_split'; import { VislibLibLayoutSplitsColumnChartChartTitleSplitProvider } from '../../../../../lib/layout/splits/column_chart/chart_title_split'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js b/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js index 2fe0cc2b7fbea..1ab8c0750ab00 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js @@ -19,7 +19,7 @@ import d3 from 'd3'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import $ from 'jquery'; import VislibLibLayoutSplitsGaugeChartChartSplitProvider from '../../../../../lib/layout/splits/gauge_chart/chart_split'; import VislibLibLayoutSplitsGaugeChartChartTitleSplitProvider from '../../../../../lib/layout/splits/gauge_chart/chart_title_split'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/types/column_layout.js b/src/legacy/ui/public/vislib/__tests__/lib/layout/types/column_layout.js index 6086b7007af58..db721a754134f 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/layout/types/column_layout.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/layout/types/column_layout.js @@ -20,7 +20,7 @@ import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VislibLibLayoutLayoutTypesProvider } from '../../../../lib/layout/layout_types'; describe('Vislib Column Layout Test Suite', function () { diff --git a/src/legacy/ui/public/vislib/__tests__/lib/types/point_series.js b/src/legacy/ui/public/vislib/__tests__/lib/types/point_series.js index f5d8e16092e0b..3688fb834f9b5 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/types/point_series.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/types/point_series.js @@ -18,7 +18,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import stackedSeries from 'fixtures/vislib/mock_data/date_histogram/_stacked_series'; import { VislibTypesPointSeries } from '../../../lib/types/point_series'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/vis_config.js b/src/legacy/ui/public/vislib/__tests__/lib/vis_config.js index 510263b37bce5..5e0f0f99c2d53 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/vis_config.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/vis_config.js @@ -19,7 +19,7 @@ import d3 from 'd3'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VislibVisConfigProvider } from '../../lib/vis_config'; import '../../../persisted_state'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/x_axis.js b/src/legacy/ui/public/vislib/__tests__/lib/x_axis.js index d55259132a794..3fad87ee851ad 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/x_axis.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/x_axis.js @@ -20,7 +20,7 @@ import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import $ from 'jquery'; import '../../../persisted_state'; import { VislibLibAxisProvider } from '../../lib/axis'; diff --git a/src/legacy/ui/public/vislib/__tests__/lib/y_axis.js b/src/legacy/ui/public/vislib/__tests__/lib/y_axis.js index b59ba8e6e3158..965c1c49e1cc5 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/y_axis.js +++ b/src/legacy/ui/public/vislib/__tests__/lib/y_axis.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import d3 from 'd3'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import $ from 'jquery'; import '../../../persisted_state'; import { VislibLibAxisProvider } from '../../lib/axis'; diff --git a/src/legacy/ui/public/vislib/__tests__/vis.js b/src/legacy/ui/public/vislib/__tests__/vis.js index acacf59fbfcdf..1079bd0ad3155 100644 --- a/src/legacy/ui/public/vislib/__tests__/vis.js +++ b/src/legacy/ui/public/vislib/__tests__/vis.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import series from 'fixtures/vislib/mock_data/date_histogram/_series'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/area_chart.js b/src/legacy/ui/public/vislib/__tests__/visualizations/area_chart.js index ac7944ae8dead..1390eecfa28dd 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/area_chart.js +++ b/src/legacy/ui/public/vislib/__tests__/visualizations/area_chart.js @@ -18,7 +18,7 @@ */ import d3 from 'd3'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/chart.js b/src/legacy/ui/public/vislib/__tests__/visualizations/chart.js index 5a9cbc0494213..916337165fab2 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/chart.js +++ b/src/legacy/ui/public/vislib/__tests__/visualizations/chart.js @@ -18,7 +18,7 @@ */ import d3 from 'd3'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { VislibVisProvider } from '../../vis'; import '../../../persisted_state'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/column_chart.js b/src/legacy/ui/public/vislib/__tests__/visualizations/column_chart.js index af76a960d9635..18ed4b4e28f21 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/column_chart.js +++ b/src/legacy/ui/public/vislib/__tests__/visualizations/column_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; import d3 from 'd3'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/gauge_chart.js b/src/legacy/ui/public/vislib/__tests__/visualizations/gauge_chart.js index 09d64beb95db3..04bcad2535538 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/gauge_chart.js +++ b/src/legacy/ui/public/vislib/__tests__/visualizations/gauge_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import $ from 'jquery'; import _ from 'lodash'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/heatmap_chart.js b/src/legacy/ui/public/vislib/__tests__/visualizations/heatmap_chart.js index 4fbf607e334b3..294ca49a64ecf 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/heatmap_chart.js +++ b/src/legacy/ui/public/vislib/__tests__/visualizations/heatmap_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; import d3 from 'd3'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/line_chart.js b/src/legacy/ui/public/vislib/__tests__/visualizations/line_chart.js index 064b422897445..98133413c8d97 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/line_chart.js +++ b/src/legacy/ui/public/vislib/__tests__/visualizations/line_chart.js @@ -18,7 +18,7 @@ */ import d3 from 'd3'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/pie_chart.js b/src/legacy/ui/public/vislib/__tests__/visualizations/pie_chart.js index be0527ba6f462..7ce81065d524f 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/pie_chart.js +++ b/src/legacy/ui/public/vislib/__tests__/visualizations/pie_chart.js @@ -18,7 +18,7 @@ */ import d3 from 'd3'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; import fixtures from 'fixtures/fake_hierarchical_data'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/time_marker.js b/src/legacy/ui/public/vislib/__tests__/visualizations/time_marker.js index c5d4cfb268ee1..1c2c0d5d5c871 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/time_marker.js +++ b/src/legacy/ui/public/vislib/__tests__/visualizations/time_marker.js @@ -18,7 +18,7 @@ */ import d3 from 'd3'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import series from 'fixtures/vislib/mock_data/date_histogram/_series'; import terms from 'fixtures/vislib/mock_data/terms/_columns'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/vis_types.js b/src/legacy/ui/public/vislib/__tests__/visualizations/vis_types.js index f4621989ab7b2..5729de277f56f 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/vis_types.js +++ b/src/legacy/ui/public/vislib/__tests__/visualizations/vis_types.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; import { VislibVisualizationsVisTypesProvider } from '../../visualizations/vis_types'; diff --git a/src/legacy/ui/public/visualize/loader/__tests__/visualization_loader.js b/src/legacy/ui/public/visualize/loader/__tests__/visualization_loader.js index 50eb3ef3d779c..ffce391fc1a07 100644 --- a/src/legacy/ui/public/visualize/loader/__tests__/visualization_loader.js +++ b/src/legacy/ui/public/visualize/loader/__tests__/visualization_loader.js @@ -18,7 +18,7 @@ */ import $ from 'jquery'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { setupAndTeardownInjectorStub } from 'test_utils/stub_get_active_injector'; diff --git a/src/legacy/ui/public/visualize/loader/__tests__/visualize_data_loader.js b/src/legacy/ui/public/visualize/loader/__tests__/visualize_data_loader.js index 4c2e31a46d7cb..e8586c6a94a79 100644 --- a/src/legacy/ui/public/visualize/loader/__tests__/visualize_data_loader.js +++ b/src/legacy/ui/public/visualize/loader/__tests__/visualize_data_loader.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { setupAndTeardownInjectorStub } from 'test_utils/stub_get_active_injector'; diff --git a/src/legacy/ui/public/visualize/loader/__tests__/visualize_loader.js b/src/legacy/ui/public/visualize/loader/__tests__/visualize_loader.js index 515c490eca97f..67daae80ea48d 100644 --- a/src/legacy/ui/public/visualize/loader/__tests__/visualize_loader.js +++ b/src/legacy/ui/public/visualize/loader/__tests__/visualize_loader.js @@ -18,7 +18,7 @@ */ import angular from 'angular'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; import { cloneDeep } from 'lodash'; diff --git a/src/legacy/ui/public/watch_multi/__tests__/watch_multi.js b/src/legacy/ui/public/watch_multi/__tests__/watch_multi.js index 9ad0c7787a93e..8c90b6c1dfbac 100644 --- a/src/legacy/ui/public/watch_multi/__tests__/watch_multi.js +++ b/src/legacy/ui/public/watch_multi/__tests__/watch_multi.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; describe('$scope.$watchMulti', function () { diff --git a/src/legacy/ui/ui_apps/__tests__/ui_app.js b/src/legacy/ui/ui_apps/__tests__/ui_app.js index 9d5a1a585d746..1e367e3d809a3 100644 --- a/src/legacy/ui/ui_apps/__tests__/ui_app.js +++ b/src/legacy/ui/ui_apps/__tests__/ui_app.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { UiApp } from '../ui_app'; import { UiNavLink } from '../../ui_nav_links'; diff --git a/src/legacy/ui/ui_bundles/__tests__/app_entry_template.js b/src/legacy/ui/ui_bundles/__tests__/app_entry_template.js index 79b57955ebd60..3a0e40073ca3e 100644 --- a/src/legacy/ui/ui_bundles/__tests__/app_entry_template.js +++ b/src/legacy/ui/ui_bundles/__tests__/app_entry_template.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { appEntryTemplate } from '../app_entry_template'; diff --git a/src/legacy/ui/ui_bundles/__tests__/ui_bundle.js b/src/legacy/ui/ui_bundles/__tests__/ui_bundle.js index f92cc79303ce6..c323e06adb599 100644 --- a/src/legacy/ui/ui_bundles/__tests__/ui_bundle.js +++ b/src/legacy/ui/ui_bundles/__tests__/ui_bundle.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { UiBundle } from '../ui_bundle'; diff --git a/src/legacy/ui/ui_exports/__tests__/collect_ui_exports.js b/src/legacy/ui/ui_exports/__tests__/collect_ui_exports.js index 85b77c6f304de..de9a26814969d 100644 --- a/src/legacy/ui/ui_exports/__tests__/collect_ui_exports.js +++ b/src/legacy/ui/ui_exports/__tests__/collect_ui_exports.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PluginPack } from '../../../plugin_discovery'; diff --git a/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js b/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js index be20ac0bded72..7969329256aa4 100644 --- a/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js +++ b/src/legacy/ui/ui_nav_links/__tests__/ui_nav_link.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { UiNavLink } from '../ui_nav_link'; diff --git a/src/legacy/ui/ui_settings/__tests__/lib/create_objects_client_stub.js b/src/legacy/ui/ui_settings/__tests__/lib/create_objects_client_stub.js index 6dbef853719e0..457ddd866c758 100644 --- a/src/legacy/ui/ui_settings/__tests__/lib/create_objects_client_stub.js +++ b/src/legacy/ui/ui_settings/__tests__/lib/create_objects_client_stub.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SavedObjectsClient } from '../../../../server/saved_objects'; export const savedObjectsClientErrors = SavedObjectsClient.errors; diff --git a/src/legacy/ui/ui_settings/__tests__/ui_settings_mixin_integration.js b/src/legacy/ui/ui_settings/__tests__/ui_settings_mixin_integration.js index b3723f89ada3b..9e8413a0f99e0 100644 --- a/src/legacy/ui/ui_settings/__tests__/ui_settings_mixin_integration.js +++ b/src/legacy/ui/ui_settings/__tests__/ui_settings_mixin_integration.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Config } from '../../../server/config'; diff --git a/src/legacy/ui/ui_settings/__tests__/ui_settings_service.js b/src/legacy/ui/ui_settings/__tests__/ui_settings_service.js index 4aa7acc5bc629..3106ba429f7ce 100644 --- a/src/legacy/ui/ui_settings/__tests__/ui_settings_service.js +++ b/src/legacy/ui/ui_settings/__tests__/ui_settings_service.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { errors as esErrors } from 'elasticsearch'; import Chance from 'chance'; import sinon from 'sinon'; diff --git a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js b/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js index 4bbb715862820..55de8a32199c5 100644 --- a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js +++ b/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { startTestServers } from '../../../../../test_utils/kbn_server'; import { createOrUpgradeSavedConfig } from '../create_or_upgrade_saved_config'; diff --git a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js b/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js index 8d865f81555ef..d047fd8bb2576 100644 --- a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js +++ b/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Chance from 'chance'; import * as getUpgradeableConfigNS from '../get_upgradeable_config'; diff --git a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/is_config_version_upgradeable.js b/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/is_config_version_upgradeable.js index 4ee79350a5e6a..734d579d23404 100644 --- a/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/is_config_version_upgradeable.js +++ b/src/legacy/ui/ui_settings/create_or_upgrade_saved_config/__tests__/is_config_version_upgradeable.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isConfigVersionUpgradeable } from '../is_config_version_upgradeable'; import { pkg } from '../../../../utils'; diff --git a/src/legacy/ui/ui_settings/routes/__tests__/doc_exists.js b/src/legacy/ui/ui_settings/routes/__tests__/doc_exists.js index 3b1af1dea88c9..824194ae1788f 100644 --- a/src/legacy/ui/ui_settings/routes/__tests__/doc_exists.js +++ b/src/legacy/ui/ui_settings/routes/__tests__/doc_exists.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { diff --git a/src/legacy/ui/ui_settings/routes/__tests__/doc_missing.js b/src/legacy/ui/ui_settings/routes/__tests__/doc_missing.js index ee05eb7d08c0e..a1fbec8ad39df 100644 --- a/src/legacy/ui/ui_settings/routes/__tests__/doc_missing.js +++ b/src/legacy/ui/ui_settings/routes/__tests__/doc_missing.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { diff --git a/src/legacy/ui/ui_settings/routes/__tests__/doc_missing_and_index_read_only.js b/src/legacy/ui/ui_settings/routes/__tests__/doc_missing_and_index_read_only.js index fa51f61e0f97e..4ef004843054c 100644 --- a/src/legacy/ui/ui_settings/routes/__tests__/doc_missing_and_index_read_only.js +++ b/src/legacy/ui/ui_settings/routes/__tests__/doc_missing_and_index_read_only.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { diff --git a/src/legacy/utils/__tests__/kbn_field_types.js b/src/legacy/utils/__tests__/kbn_field_types.js index af4e633c98c1f..f94438b10ca58 100644 --- a/src/legacy/utils/__tests__/kbn_field_types.js +++ b/src/legacy/utils/__tests__/kbn_field_types.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Chance from 'chance'; const chance = new Chance(); diff --git a/src/legacy/utils/__tests__/unset.js b/src/legacy/utils/__tests__/unset.js index 5540c2cc23aeb..69122e06ac572 100644 --- a/src/legacy/utils/__tests__/unset.js +++ b/src/legacy/utils/__tests__/unset.js @@ -18,7 +18,7 @@ */ import { unset } from '../unset'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('unset(obj, key)', function () { describe('invalid input', function () { diff --git a/src/legacy/utils/strings/__tests__/comma_separated_list.js b/src/legacy/utils/strings/__tests__/comma_separated_list.js index a52187ef47e74..e8f16f045765a 100644 --- a/src/legacy/utils/strings/__tests__/comma_separated_list.js +++ b/src/legacy/utils/strings/__tests__/comma_separated_list.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { parseCommaSeparatedList } from '../comma_separated_list'; diff --git a/src/legacy/utils/strings/__tests__/prose.js b/src/legacy/utils/strings/__tests__/prose.js index 3655a828766f0..d99f5f196fb67 100644 --- a/src/legacy/utils/strings/__tests__/prose.js +++ b/src/legacy/utils/strings/__tests__/prose.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { formatListAsProse } from '../prose'; diff --git a/src/optimize/bundles_route/__tests__/bundles_route.js b/src/optimize/bundles_route/__tests__/bundles_route.js index 87638c311bca1..480e7e2a0fb8f 100644 --- a/src/optimize/bundles_route/__tests__/bundles_route.js +++ b/src/optimize/bundles_route/__tests__/bundles_route.js @@ -22,7 +22,7 @@ import { readFileSync } from 'fs'; import crypto from 'crypto'; import Chance from 'chance'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Hapi from 'hapi'; import Inert from 'inert'; import sinon from 'sinon'; diff --git a/src/test_utils/__tests__/get_url.js b/src/test_utils/__tests__/get_url.js index b4fad9d0fa889..d071e34ee116e 100644 --- a/src/test_utils/__tests__/get_url.js +++ b/src/test_utils/__tests__/get_url.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import getUrl from '../get_url'; describe('getUrl', function () { diff --git a/src/test_utils/expect_deep_equal.js b/src/test_utils/expect_deep_equal.js index 0d4207c233b99..e3e24cbdf5dc9 100644 --- a/src/test_utils/expect_deep_equal.js +++ b/src/test_utils/expect_deep_equal.js @@ -18,7 +18,7 @@ */ import { isEqual } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; // expect.js's `eql` method provides nice error messages but sometimes misses things // since it only tests loose (==) equality. This function uses lodash's `isEqual` as a diff --git a/test/api_integration/apis/general/cookies.js b/test/api_integration/apis/general/cookies.js index d377ca1eac6ba..7791f3bde4061 100644 --- a/test/api_integration/apis/general/cookies.js +++ b/test/api_integration/apis/general/cookies.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/general/csp.js b/test/api_integration/apis/general/csp.js index 3ae7625677277..f3501aa55adaa 100644 --- a/test/api_integration/apis/general/csp.js +++ b/test/api_integration/apis/general/csp.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/home/sample_data.js b/test/api_integration/apis/home/sample_data.js index e71c98eb9679c..81fb6235520e0 100644 --- a/test/api_integration/apis/home/sample_data.js +++ b/test/api_integration/apis/home/sample_data.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { diff --git a/test/api_integration/apis/index_patterns/es_errors/errors.js b/test/api_integration/apis/index_patterns/es_errors/errors.js index 94ac82a6118dd..7e04e3f7204d7 100644 --- a/test/api_integration/apis/index_patterns/es_errors/errors.js +++ b/test/api_integration/apis/index_patterns/es_errors/errors.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { errors as esErrors } from 'elasticsearch'; import Boom from 'boom'; diff --git a/test/api_integration/apis/index_patterns/es_errors/lib/get_es_errors.js b/test/api_integration/apis/index_patterns/es_errors/lib/get_es_errors.js index da375e76d54b7..f303bca0da574 100644 --- a/test/api_integration/apis/index_patterns/es_errors/lib/get_es_errors.js +++ b/test/api_integration/apis/index_patterns/es_errors/lib/get_es_errors.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export async function getIndexNotFoundError(es) { try { diff --git a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/pattern.js b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/pattern.js index 58f5407f81de3..e0e18b4734ff6 100644 --- a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/pattern.js +++ b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/pattern.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js index c8030fd3e4e89..2201b56316657 100644 --- a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js +++ b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js index f0f9d73dc6ec1..e2eebfa9e6d84 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js index 26497d317f272..8a2af8040b2ff 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { sortBy } from 'lodash'; export default function ({ getService }) { diff --git a/test/api_integration/apis/kql_telemetry/kql_telemetry.js b/test/api_integration/apis/kql_telemetry/kql_telemetry.js index 6ed48434064e7..b17dec2ef437b 100644 --- a/test/api_integration/apis/kql_telemetry/kql_telemetry.js +++ b/test/api_integration/apis/kql_telemetry/kql_telemetry.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Promise from 'bluebird'; import { get } from 'lodash'; diff --git a/test/api_integration/apis/management/saved_objects/relationships.js b/test/api_integration/apis/management/saved_objects/relationships.js index e31a5fe3aaa7e..2a866245b1aa4 100644 --- a/test/api_integration/apis/management/saved_objects/relationships.js +++ b/test/api_integration/apis/management/saved_objects/relationships.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; const Joi = require('joi'); export default function ({ getService }) { diff --git a/test/api_integration/apis/saved_objects/bulk_create.js b/test/api_integration/apis/saved_objects/bulk_create.js index 44aaaf0fa55b1..e77e08d949f2b 100644 --- a/test/api_integration/apis/saved_objects/bulk_create.js +++ b/test/api_integration/apis/saved_objects/bulk_create.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/saved_objects/bulk_get.js b/test/api_integration/apis/saved_objects/bulk_get.js index da208a5cbe70a..1d129b7d738e2 100644 --- a/test/api_integration/apis/saved_objects/bulk_get.js +++ b/test/api_integration/apis/saved_objects/bulk_get.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/saved_objects/create.js b/test/api_integration/apis/saved_objects/create.js index 17b4fc55fbb4e..ccc436a757a8f 100644 --- a/test/api_integration/apis/saved_objects/create.js +++ b/test/api_integration/apis/saved_objects/create.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/saved_objects/delete.js b/test/api_integration/apis/saved_objects/delete.js index 72cf9a9cbf525..a9037bf697406 100644 --- a/test/api_integration/apis/saved_objects/delete.js +++ b/test/api_integration/apis/saved_objects/delete.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/saved_objects/export.js b/test/api_integration/apis/saved_objects/export.js index 078ecd44aa4c7..75829c7507870 100644 --- a/test/api_integration/apis/saved_objects/export.js +++ b/test/api_integration/apis/saved_objects/export.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/saved_objects/find.js b/test/api_integration/apis/saved_objects/find.js index f6e07fd4fb5c6..3ad2ca3f50571 100644 --- a/test/api_integration/apis/saved_objects/find.js +++ b/test/api_integration/apis/saved_objects/find.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/saved_objects/get.js b/test/api_integration/apis/saved_objects/get.js index 0734918f5f3e4..58d12af7f9d06 100644 --- a/test/api_integration/apis/saved_objects/get.js +++ b/test/api_integration/apis/saved_objects/get.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/saved_objects/import.js b/test/api_integration/apis/saved_objects/import.js index b38109d32e7ef..19fd051e5f443 100644 --- a/test/api_integration/apis/saved_objects/import.js +++ b/test/api_integration/apis/saved_objects/import.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { join } from 'path'; export default function ({ getService }) { diff --git a/test/api_integration/apis/saved_objects/resolve_import_errors.js b/test/api_integration/apis/saved_objects/resolve_import_errors.js index adffbe03117ff..84867960a8e3b 100644 --- a/test/api_integration/apis/saved_objects/resolve_import_errors.js +++ b/test/api_integration/apis/saved_objects/resolve_import_errors.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { join } from 'path'; export default function ({ getService }) { diff --git a/test/api_integration/apis/saved_objects/update.js b/test/api_integration/apis/saved_objects/update.js index 4e56a9f120881..25a97d9e00b78 100644 --- a/test/api_integration/apis/saved_objects/update.js +++ b/test/api_integration/apis/saved_objects/update.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/scripts/languages.js b/test/api_integration/apis/scripts/languages.js index b8145f0344682..89da7ed2083ac 100644 --- a/test/api_integration/apis/scripts/languages.js +++ b/test/api_integration/apis/scripts/languages.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/search/count.js b/test/api_integration/apis/search/count.js index 1fc4cbf9b6ad1..de0d161551d95 100644 --- a/test/api_integration/apis/search/count.js +++ b/test/api_integration/apis/search/count.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const esArchiver = getService('esArchiver'); diff --git a/test/api_integration/apis/shorten/index.js b/test/api_integration/apis/shorten/index.js index fdd5421b7774f..5e6ab4c354d44 100644 --- a/test/api_integration/apis/shorten/index.js +++ b/test/api_integration/apis/shorten/index.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const esArchiver = getService('esArchiver'); diff --git a/test/api_integration/apis/stats/stats.js b/test/api_integration/apis/stats/stats.js index ef0d76e0e36a4..a02c3f1408c06 100644 --- a/test/api_integration/apis/stats/stats.js +++ b/test/api_integration/apis/stats/stats.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; const assertStatsAndMetrics = body => { expect(body.kibana.name).to.be.a('string'); diff --git a/test/api_integration/apis/status/status.js b/test/api_integration/apis/status/status.js index 08ab6fc7667a1..c0aa080ce2480 100644 --- a/test/api_integration/apis/status/status.js +++ b/test/api_integration/apis/status/status.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/user_action/user_action.js b/test/api_integration/apis/user_action/user_action.js index ca1d58d9dbb41..db4485c8f14f3 100644 --- a/test/api_integration/apis/user_action/user_action.js +++ b/test/api_integration/apis/user_action/user_action.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { get } from 'lodash'; export default function ({ getService }) { diff --git a/test/functional/apps/console/_console.ts b/test/functional/apps/console/_console.ts index d4937962a2241..1fda35f2bf1ae 100644 --- a/test/functional/apps/console/_console.ts +++ b/test/functional/apps/console/_console.ts @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; const DEFAULT_REQUEST = ` diff --git a/test/functional/apps/context/_discover_navigation.js b/test/functional/apps/context/_discover_navigation.js index 3a6c357c1ad07..19b43f5e3ffd3 100644 --- a/test/functional/apps/context/_discover_navigation.js +++ b/test/functional/apps/context/_discover_navigation.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; const TEST_DISCOVER_START_TIME = '2015-09-19 06:31:44.000'; const TEST_DISCOVER_END_TIME = '2015-09-23 18:31:44.000'; diff --git a/test/functional/apps/context/_filters.js b/test/functional/apps/context/_filters.js index fe3a16d2d42f4..6823d78e23305 100644 --- a/test/functional/apps/context/_filters.js +++ b/test/functional/apps/context/_filters.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; const TEST_INDEX_PATTERN = 'logstash-*'; const TEST_ANCHOR_TYPE = '_doc'; diff --git a/test/functional/apps/context/_size.js b/test/functional/apps/context/_size.js index 3513a2fc53768..749ab797fc6ce 100644 --- a/test/functional/apps/context/_size.js +++ b/test/functional/apps/context/_size.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; const TEST_INDEX_PATTERN = 'logstash-*'; const TEST_ANCHOR_TYPE = '_doc'; diff --git a/test/functional/apps/dashboard/bwc_shared_urls.js b/test/functional/apps/dashboard/bwc_shared_urls.js index 7c3acfba906a3..69ded31fcc1d1 100644 --- a/test/functional/apps/dashboard/bwc_shared_urls.js +++ b/test/functional/apps/dashboard/bwc_shared_urls.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['dashboard', 'header']); diff --git a/test/functional/apps/dashboard/create_and_add_embeddables.js b/test/functional/apps/dashboard/create_and_add_embeddables.js index c138e3462e801..84c16feef0b5a 100644 --- a/test/functional/apps/dashboard/create_and_add_embeddables.js +++ b/test/functional/apps/dashboard/create_and_add_embeddables.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { VisualizeConstants diff --git a/test/functional/apps/dashboard/dashboard_clone.js b/test/functional/apps/dashboard/dashboard_clone.js index 817d0e6dcd690..493c31578e357 100644 --- a/test/functional/apps/dashboard/dashboard_clone.js +++ b/test/functional/apps/dashboard/dashboard_clone.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/dashboard_filter_bar.js b/test/functional/apps/dashboard/dashboard_filter_bar.js index a393a949377e1..1b29a67a0c778 100644 --- a/test/functional/apps/dashboard/dashboard_filter_bar.js +++ b/test/functional/apps/dashboard/dashboard_filter_bar.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const dashboardExpect = getService('dashboardExpect'); diff --git a/test/functional/apps/dashboard/dashboard_filtering.js b/test/functional/apps/dashboard/dashboard_filtering.js index 8c2ef2ea37a13..c3f426e7d5687 100644 --- a/test/functional/apps/dashboard/dashboard_filtering.js +++ b/test/functional/apps/dashboard/dashboard_filtering.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; /** * Test the querying capabilities of dashboard, and make sure visualizations show the expected results, especially diff --git a/test/functional/apps/dashboard/dashboard_grid.js b/test/functional/apps/dashboard/dashboard_grid.js index 6aacd82003bc4..f8eb220d60985 100644 --- a/test/functional/apps/dashboard/dashboard_grid.js +++ b/test/functional/apps/dashboard/dashboard_grid.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const browser = getService('browser'); diff --git a/test/functional/apps/dashboard/dashboard_listing.js b/test/functional/apps/dashboard/dashboard_listing.js index 2545ef1b4dae9..84ab47ae592e2 100644 --- a/test/functional/apps/dashboard/dashboard_listing.js +++ b/test/functional/apps/dashboard/dashboard_listing.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['dashboard', 'header', 'common']); diff --git a/test/functional/apps/dashboard/dashboard_options.js b/test/functional/apps/dashboard/dashboard_options.js index 02dc1e7a4af7b..db1c7091a78f5 100644 --- a/test/functional/apps/dashboard/dashboard_options.js +++ b/test/functional/apps/dashboard/dashboard_options.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/dashboard_query_bar.js b/test/functional/apps/dashboard/dashboard_query_bar.js index 224ae819de8d1..f6f3b8a894518 100644 --- a/test/functional/apps/dashboard/dashboard_query_bar.js +++ b/test/functional/apps/dashboard/dashboard_query_bar.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); diff --git a/test/functional/apps/dashboard/dashboard_save.js b/test/functional/apps/dashboard/dashboard_save.js index 31b155916607a..83ddaf4804722 100644 --- a/test/functional/apps/dashboard/dashboard_save.js +++ b/test/functional/apps/dashboard/dashboard_save.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects }) { const PageObjects = getPageObjects(['dashboard', 'header']); diff --git a/test/functional/apps/dashboard/dashboard_snapshots.js b/test/functional/apps/dashboard/dashboard_snapshots.js index 0f382f79cd09c..62c2e22546023 100644 --- a/test/functional/apps/dashboard/dashboard_snapshots.js +++ b/test/functional/apps/dashboard/dashboard_snapshots.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects, updateBaselines }) { const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'common']); diff --git a/test/functional/apps/dashboard/dashboard_state.js b/test/functional/apps/dashboard/dashboard_state.js index ed8999eb5977e..ca50e81d924e5 100644 --- a/test/functional/apps/dashboard/dashboard_state.js +++ b/test/functional/apps/dashboard/dashboard_state.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PIE_CHART_VIS_NAME, AREA_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; import { diff --git a/test/functional/apps/dashboard/dashboard_time.js b/test/functional/apps/dashboard/dashboard_time.js index b34d061f608a0..8ce77f7ee46f5 100644 --- a/test/functional/apps/dashboard/dashboard_time.js +++ b/test/functional/apps/dashboard/dashboard_time.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; const dashboardName = 'Dashboard Test Time'; diff --git a/test/functional/apps/dashboard/data_shared_attributes.js b/test/functional/apps/dashboard/data_shared_attributes.js index 27ac2184071f8..8a760b6f35d01 100644 --- a/test/functional/apps/dashboard/data_shared_attributes.js +++ b/test/functional/apps/dashboard/data_shared_attributes.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/embed_mode.js b/test/functional/apps/dashboard/embed_mode.js index 22fb42108ce2c..f5b99bf30ca95 100644 --- a/test/functional/apps/dashboard/embed_mode.js +++ b/test/functional/apps/dashboard/embed_mode.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/embeddable_rendering.js b/test/functional/apps/dashboard/embeddable_rendering.js index 97d8e2ec15f66..614a66c4f473c 100644 --- a/test/functional/apps/dashboard/embeddable_rendering.js +++ b/test/functional/apps/dashboard/embeddable_rendering.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; /** * This tests both that one of each visualization can be added to a dashboard (as opposed to opening an existing diff --git a/test/functional/apps/dashboard/empty_dashboard.js b/test/functional/apps/dashboard/empty_dashboard.js index 36f57d48c5100..26745ed61910a 100644 --- a/test/functional/apps/dashboard/empty_dashboard.js +++ b/test/functional/apps/dashboard/empty_dashboard.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const testSubjects = getService('testSubjects'); diff --git a/test/functional/apps/dashboard/full_screen_mode.js b/test/functional/apps/dashboard/full_screen_mode.js index 68bb2f58be8d0..0475c40eff0c4 100644 --- a/test/functional/apps/dashboard/full_screen_mode.js +++ b/test/functional/apps/dashboard/full_screen_mode.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/panel_controls.js b/test/functional/apps/dashboard/panel_controls.js index 39f1eca464947..c5c98f191421a 100644 --- a/test/functional/apps/dashboard/panel_controls.js +++ b/test/functional/apps/dashboard/panel_controls.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; import { diff --git a/test/functional/apps/dashboard/panel_expand_toggle.js b/test/functional/apps/dashboard/panel_expand_toggle.js index af74fe6a48290..e61d4f4015a09 100644 --- a/test/functional/apps/dashboard/panel_expand_toggle.js +++ b/test/functional/apps/dashboard/panel_expand_toggle.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/time_zones.js b/test/functional/apps/dashboard/time_zones.js index 514b0366d19bb..10f91448c3705 100644 --- a/test/functional/apps/dashboard/time_zones.js +++ b/test/functional/apps/dashboard/time_zones.js @@ -18,7 +18,7 @@ */ import path from 'path'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const pieChart = getService('pieChart'); diff --git a/test/functional/apps/dashboard/view_edit.js b/test/functional/apps/dashboard/view_edit.js index 7851d5320f2e3..edef26dbc2d34 100644 --- a/test/functional/apps/dashboard/view_edit.js +++ b/test/functional/apps/dashboard/view_edit.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const queryBar = getService('queryBar'); diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index d4167b5cfae7e..e6c783a801564 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/discover/_errors.js b/test/functional/apps/discover/_errors.js index 87cdba3d9ed68..060639d5c49bc 100644 --- a/test/functional/apps/discover/_errors.js +++ b/test/functional/apps/discover/_errors.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); diff --git a/test/functional/apps/discover/_field_data.js b/test/functional/apps/discover/_field_data.js index d295a502094ab..dc2c1b468f985 100644 --- a/test/functional/apps/discover/_field_data.js +++ b/test/functional/apps/discover/_field_data.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/discover/_inspector.js b/test/functional/apps/discover/_inspector.js index 5b269ef6902d4..6a2144e829920 100644 --- a/test/functional/apps/discover/_inspector.js +++ b/test/functional/apps/discover/_inspector.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['common', 'visualize', 'timePicker']); diff --git a/test/functional/apps/discover/_large_string.js b/test/functional/apps/discover/_large_string.js index 9feed7c9202e9..426779bd0c495 100644 --- a/test/functional/apps/discover/_large_string.js +++ b/test/functional/apps/discover/_large_string.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); diff --git a/test/functional/apps/discover/_shared_links.js b/test/functional/apps/discover/_shared_links.js index bfe90cf17003c..4b85593d1f02c 100644 --- a/test/functional/apps/discover/_shared_links.js +++ b/test/functional/apps/discover/_shared_links.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/discover/_sidebar.js b/test/functional/apps/discover/_sidebar.js index 865b0ea7d71b7..26a47b0a12422 100644 --- a/test/functional/apps/discover/_sidebar.js +++ b/test/functional/apps/discover/_sidebar.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/discover/_source_filters.js b/test/functional/apps/discover/_source_filters.js index a230c5625ac8d..14ecde383fd44 100644 --- a/test/functional/apps/discover/_source_filters.js +++ b/test/functional/apps/discover/_source_filters.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/getting_started/_shakespeare.js b/test/functional/apps/getting_started/_shakespeare.js index 4dd7639001104..39bb6acb7494e 100644 --- a/test/functional/apps/getting_started/_shakespeare.js +++ b/test/functional/apps/getting_started/_shakespeare.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/home/_add_data.js b/test/functional/apps/home/_add_data.js index f6cf02e518260..7b6fa5c1614de 100644 --- a/test/functional/apps/home/_add_data.js +++ b/test/functional/apps/home/_add_data.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/home/_home.js b/test/functional/apps/home/_home.js index 3eaa0c5bdef1c..f4a9b53d89ecb 100644 --- a/test/functional/apps/home/_home.js +++ b/test/functional/apps/home/_home.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/home/_navigation.js b/test/functional/apps/home/_navigation.js index c31b3a6100cd2..cc297856e0458 100644 --- a/test/functional/apps/home/_navigation.js +++ b/test/functional/apps/home/_navigation.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/home/_sample_data.js b/test/functional/apps/home/_sample_data.js index 700eea39f4613..e77996224094f 100644 --- a/test/functional/apps/home/_sample_data.js +++ b/test/functional/apps/home/_sample_data.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/management/_create_index_pattern_wizard.js b/test/functional/apps/management/_create_index_pattern_wizard.js index 5cde83bed5f99..3539fd975b746 100644 --- a/test/functional/apps/management/_create_index_pattern_wizard.js +++ b/test/functional/apps/management/_create_index_pattern_wizard.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/management/_handle_alias.js b/test/functional/apps/management/_handle_alias.js index 7a866a0274bcb..1556897d69387 100644 --- a/test/functional/apps/management/_handle_alias.js +++ b/test/functional/apps/management/_handle_alias.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); diff --git a/test/functional/apps/management/_handle_version_conflict.js b/test/functional/apps/management/_handle_version_conflict.js index 722e855edf3ac..ce5f968a37115 100644 --- a/test/functional/apps/management/_handle_version_conflict.js +++ b/test/functional/apps/management/_handle_version_conflict.js @@ -27,7 +27,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); diff --git a/test/functional/apps/management/_import_objects.js b/test/functional/apps/management/_import_objects.js index 7fc7bf276289b..73e5e7e0cecb3 100644 --- a/test/functional/apps/management/_import_objects.js +++ b/test/functional/apps/management/_import_objects.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import path from 'path'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/management/_index_pattern_create_delete.js b/test/functional/apps/management/_index_pattern_create_delete.js index 251a17ec1bfdc..b49bdd5bf738f 100644 --- a/test/functional/apps/management/_index_pattern_create_delete.js +++ b/test/functional/apps/management/_index_pattern_create_delete.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/management/_index_pattern_filter.js b/test/functional/apps/management/_index_pattern_filter.js index a27d52d75b35f..0985639ac3c97 100644 --- a/test/functional/apps/management/_index_pattern_filter.js +++ b/test/functional/apps/management/_index_pattern_filter.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/management/_index_pattern_popularity.js b/test/functional/apps/management/_index_pattern_popularity.js index 32ee0a8934c48..72f368c9c714b 100644 --- a/test/functional/apps/management/_index_pattern_popularity.js +++ b/test/functional/apps/management/_index_pattern_popularity.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/management/_index_pattern_results_sort.js b/test/functional/apps/management/_index_pattern_results_sort.js index f8cfb55db0014..d834ad0c1dfd4 100644 --- a/test/functional/apps/management/_index_pattern_results_sort.js +++ b/test/functional/apps/management/_index_pattern_results_sort.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/management/_kibana_settings.js b/test/functional/apps/management/_kibana_settings.js index 08cdfa3494e81..084523e006157 100644 --- a/test/functional/apps/management/_kibana_settings.js +++ b/test/functional/apps/management/_kibana_settings.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/management/_mgmt_import_saved_objects.js b/test/functional/apps/management/_mgmt_import_saved_objects.js index 914c989cf1c62..973e394078c40 100644 --- a/test/functional/apps/management/_mgmt_import_saved_objects.js +++ b/test/functional/apps/management/_mgmt_import_saved_objects.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import path from 'path'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js index 86e7ab7b51a30..a3077e965dd4c 100644 --- a/test/functional/apps/management/_scripted_fields.js +++ b/test/functional/apps/management/_scripted_fields.js @@ -29,7 +29,7 @@ // 3. Filter in Discover by the scripted field // 4. Visualize with aggregation on the scripted field by clicking discover.clickFieldListItemVisualize -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/management/_scripted_fields_filter.js b/test/functional/apps/management/_scripted_fields_filter.js index 21be262e1809b..8783e5a10c195 100644 --- a/test/functional/apps/management/_scripted_fields_filter.js +++ b/test/functional/apps/management/_scripted_fields_filter.js @@ -18,7 +18,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/management/_scripted_fields_preview.js b/test/functional/apps/management/_scripted_fields_preview.js index 093d242ba3681..f6f2de7c793d1 100644 --- a/test/functional/apps/management/_scripted_fields_preview.js +++ b/test/functional/apps/management/_scripted_fields_preview.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const browser = getService('browser'); diff --git a/test/functional/apps/management/_test_huge_fields.js b/test/functional/apps/management/_test_huge_fields.js index 3fde7937a769d..57b65c33055db 100644 --- a/test/functional/apps/management/_test_huge_fields.js +++ b/test/functional/apps/management/_test_huge_fields.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); diff --git a/test/functional/apps/status_page/index.js b/test/functional/apps/status_page/index.js index 52d26cd9f3a45..34f2df287dd6b 100644 --- a/test/functional/apps/status_page/index.js +++ b/test/functional/apps/status_page/index.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/test/functional/apps/timelion/_expression_typeahead.js b/test/functional/apps/timelion/_expression_typeahead.js index aca178a906a86..7cc0740823f3c 100644 --- a/test/functional/apps/timelion/_expression_typeahead.js +++ b/test/functional/apps/timelion/_expression_typeahead.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects }) { const PageObjects = getPageObjects(['common', 'timelion', 'settings', 'timePicker']); diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js index 1fffbc2759355..1799a72e5eb11 100644 --- a/test/functional/apps/visualize/_area_chart.js +++ b/test/functional/apps/visualize/_area_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_chart_types.js b/test/functional/apps/visualize/_chart_types.js index 0912e1536e87a..596c3001285f3 100644 --- a/test/functional/apps/visualize/_chart_types.js +++ b/test/functional/apps/visualize/_chart_types.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_data_table.js b/test/functional/apps/visualize/_data_table.js index 16942dc26e57e..02fa7dd62711c 100644 --- a/test/functional/apps/visualize/_data_table.js +++ b/test/functional/apps/visualize/_data_table.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_data_table_nontimeindex.js b/test/functional/apps/visualize/_data_table_nontimeindex.js index eeb58c197c0b5..102b70ca8a6bc 100644 --- a/test/functional/apps/visualize/_data_table_nontimeindex.js +++ b/test/functional/apps/visualize/_data_table_nontimeindex.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_embedding_chart.js b/test/functional/apps/visualize/_embedding_chart.js index b6caa77d32406..0b59699d47755 100644 --- a/test/functional/apps/visualize/_embedding_chart.js +++ b/test/functional/apps/visualize/_embedding_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const filterBar = getService('filterBar'); diff --git a/test/functional/apps/visualize/_experimental_vis.js b/test/functional/apps/visualize/_experimental_vis.js index 6cce432fd2c31..386185cd9fcc5 100644 --- a/test/functional/apps/visualize/_experimental_vis.js +++ b/test/functional/apps/visualize/_experimental_vis.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default ({ getService, getPageObjects }) => { const log = getService('log'); diff --git a/test/functional/apps/visualize/_gauge_chart.js b/test/functional/apps/visualize/_gauge_chart.js index 080f3eaf52eb6..d58a2cab872bb 100644 --- a/test/functional/apps/visualize/_gauge_chart.js +++ b/test/functional/apps/visualize/_gauge_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_heatmap_chart.js b/test/functional/apps/visualize/_heatmap_chart.js index 795cfbe0e0763..075585b4216f4 100644 --- a/test/functional/apps/visualize/_heatmap_chart.js +++ b/test/functional/apps/visualize/_heatmap_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_histogram_request_start.js b/test/functional/apps/visualize/_histogram_request_start.js index 95eda5003e7f5..e1642c1383fbe 100644 --- a/test/functional/apps/visualize/_histogram_request_start.js +++ b/test/functional/apps/visualize/_histogram_request_start.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_input_control_vis.js b/test/functional/apps/visualize/_input_control_vis.js index 8afdaccf42320..a10c0284b3e7f 100644 --- a/test/functional/apps/visualize/_input_control_vis.js +++ b/test/functional/apps/visualize/_input_control_vis.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const filterBar = getService('filterBar'); diff --git a/test/functional/apps/visualize/_lab_mode.js b/test/functional/apps/visualize/_lab_mode.js index d45d9cc636622..68440c68e358a 100644 --- a/test/functional/apps/visualize/_lab_mode.js +++ b/test/functional/apps/visualize/_lab_mode.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_line_chart.js b/test/functional/apps/visualize/_line_chart.js index 350168006227f..e291e58780bd3 100644 --- a/test/functional/apps/visualize/_line_chart.js +++ b/test/functional/apps/visualize/_line_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_linked_saved_searches.js b/test/functional/apps/visualize/_linked_saved_searches.js index 9a80126f5447c..5343873e9e0a5 100644 --- a/test/functional/apps/visualize/_linked_saved_searches.js +++ b/test/functional/apps/visualize/_linked_saved_searches.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const filterBar = getService('filterBar'); diff --git a/test/functional/apps/visualize/_markdown_vis.js b/test/functional/apps/visualize/_markdown_vis.js index 7d6ee24083c49..4fca691153b36 100644 --- a/test/functional/apps/visualize/_markdown_vis.js +++ b/test/functional/apps/visualize/_markdown_vis.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['common', 'visualize', 'header']); diff --git a/test/functional/apps/visualize/_metric_chart.js b/test/functional/apps/visualize/_metric_chart.js index fbece9f724814..9046935285534 100644 --- a/test/functional/apps/visualize/_metric_chart.js +++ b/test/functional/apps/visualize/_metric_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_pie_chart.js b/test/functional/apps/visualize/_pie_chart.js index 853cabef206f4..583f8328a29ec 100644 --- a/test/functional/apps/visualize/_pie_chart.js +++ b/test/functional/apps/visualize/_pie_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_point_series_options.js b/test/functional/apps/visualize/_point_series_options.js index 5d5729e75cafb..8e01b87309a07 100644 --- a/test/functional/apps/visualize/_point_series_options.js +++ b/test/functional/apps/visualize/_point_series_options.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_region_map.js b/test/functional/apps/visualize/_region_map.js index f724e0029fd7e..053e1bafdbe64 100644 --- a/test/functional/apps/visualize/_region_map.js +++ b/test/functional/apps/visualize/_region_map.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_shared_item.js b/test/functional/apps/visualize/_shared_item.js index 85861f21a69d5..9fe38be15a741 100644 --- a/test/functional/apps/visualize/_shared_item.js +++ b/test/functional/apps/visualize/_shared_item.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_tag_cloud.js b/test/functional/apps/visualize/_tag_cloud.js index 693e435e810b4..116c5d10019e8 100644 --- a/test/functional/apps/visualize/_tag_cloud.js +++ b/test/functional/apps/visualize/_tag_cloud.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const filterBar = getService('filterBar'); diff --git a/test/functional/apps/visualize/_tile_map.js b/test/functional/apps/visualize/_tile_map.js index a739ae857717f..7d097214c3389 100644 --- a/test/functional/apps/visualize/_tile_map.js +++ b/test/functional/apps/visualize/_tile_map.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index 6cb5ab6807f51..8018c69bdec20 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; // tslint:disable-next-line:no-default-export diff --git a/test/functional/apps/visualize/_tsvb_markdown.ts b/test/functional/apps/visualize/_tsvb_markdown.ts index 55a5f6f79dc2b..3e62eba78a528 100644 --- a/test/functional/apps/visualize/_tsvb_markdown.ts +++ b/test/functional/apps/visualize/_tsvb_markdown.ts @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; // tslint:disable-next-line:no-default-export diff --git a/test/functional/apps/visualize/_vega_chart.js b/test/functional/apps/visualize/_vega_chart.js index 1e7fe5b2fce2f..186318ebe6325 100644 --- a/test/functional/apps/visualize/_vega_chart.js +++ b/test/functional/apps/visualize/_vega_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['common', 'header', 'timePicker', 'visualize']); diff --git a/test/functional/apps/visualize/_vertical_bar_chart.js b/test/functional/apps/visualize/_vertical_bar_chart.js index b5e7bd122560d..54cda5a9ed8b6 100644 --- a/test/functional/apps/visualize/_vertical_bar_chart.js +++ b/test/functional/apps/visualize/_vertical_bar_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_vertical_bar_chart_nontimeindex.js b/test/functional/apps/visualize/_vertical_bar_chart_nontimeindex.js index 992521094fe71..e845742036e80 100644 --- a/test/functional/apps/visualize/_vertical_bar_chart_nontimeindex.js +++ b/test/functional/apps/visualize/_vertical_bar_chart_nontimeindex.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_visualize_listing.js b/test/functional/apps/visualize/_visualize_listing.js index 016514c70fad6..fda15510b4691 100644 --- a/test/functional/apps/visualize/_visualize_listing.js +++ b/test/functional/apps/visualize/_visualize_listing.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects }) { const PageObjects = getPageObjects(['visualize', 'header', 'common']); diff --git a/test/functional/page_objects/common_page.js b/test/functional/page_objects/common_page.js index 9962aa2049431..90a8689cfb514 100644 --- a/test/functional/page_objects/common_page.js +++ b/test/functional/page_objects/common_page.js @@ -18,7 +18,7 @@ */ import { delay } from 'bluebird'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import getUrl from '../../../src/test_utils/get_url'; diff --git a/test/functional/page_objects/discover_page.js b/test/functional/page_objects/discover_page.js index 531fd9f984a0b..502dbf5de17cb 100644 --- a/test/functional/page_objects/discover_page.js +++ b/test/functional/page_objects/discover_page.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function DiscoverPageProvider({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/page_objects/settings_page.js b/test/functional/page_objects/settings_page.js index 815f1a851b3f3..2e728db3b388d 100644 --- a/test/functional/page_objects/settings_page.js +++ b/test/functional/page_objects/settings_page.js @@ -18,7 +18,7 @@ */ import { map as mapAsync } from 'bluebird'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function SettingsPageProvider({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/page_objects/visualize_page.js b/test/functional/page_objects/visualize_page.js index d7506442aabc8..10822b92219bb 100644 --- a/test/functional/page_objects/visualize_page.js +++ b/test/functional/page_objects/visualize_page.js @@ -19,7 +19,7 @@ import { VisualizeConstants } from '../../../src/legacy/core_plugins/kibana/public/visualize/visualize_constants'; import Bluebird from 'bluebird'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function VisualizePageProvider({ getService, getPageObjects, updateBaselines }) { const browser = getService('browser'); diff --git a/test/functional/services/dashboard/expectations.js b/test/functional/services/dashboard/expectations.js index e8f85251eefa9..cd610e8a5f02d 100644 --- a/test/functional/services/dashboard/expectations.js +++ b/test/functional/services/dashboard/expectations.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function DashboardExpectProvider({ getService, getPageObjects }) { const log = getService('log'); diff --git a/test/functional/services/inspector.js b/test/functional/services/inspector.js index eb0de451b2400..8a3c54b6556a7 100644 --- a/test/functional/services/inspector.js +++ b/test/functional/services/inspector.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function InspectorProvider({ getService }) { const log = getService('log'); diff --git a/test/functional/services/remote/__tests__/remote_default_window_size.js b/test/functional/services/remote/__tests__/remote_default_window_size.js index ffa66bcc7c892..c5ef5fcc3d035 100644 --- a/test/functional/services/remote/__tests__/remote_default_window_size.js +++ b/test/functional/services/remote/__tests__/remote_default_window_size.js @@ -19,7 +19,7 @@ import { fork } from 'child_process'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const FTR_SCRIPT = require.resolve('../../../../../scripts/functional_test_runner'); const CONFIG_PATH = require.resolve('./fixtures/several_nested_window_size_changes/config.js'); diff --git a/test/functional/services/snapshots.js b/test/functional/services/snapshots.js index b19149a8a1af0..131be48dd3b1b 100644 --- a/test/functional/services/snapshots.js +++ b/test/functional/services/snapshots.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { dirname, resolve } from 'path'; import { writeFile, readFileSync } from 'fs'; import { fromNode as fcb, promisify } from 'bluebird'; diff --git a/test/functional/services/visualizations/pie_chart.js b/test/functional/services/visualizations/pie_chart.js index c5d0d68dec399..cad3f4a589b44 100644 --- a/test/functional/services/visualizations/pie_chart.js +++ b/test/functional/services/visualizations/pie_chart.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function PieChartProvider({ getService }) { const log = getService('log'); diff --git a/test/interpreter_functional/test_suites/run_pipeline/basic.js b/test/interpreter_functional/test_suites/run_pipeline/basic.js index d1ca3240fef19..183fb8e2f1db1 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/basic.js +++ b/test/interpreter_functional/test_suites/run_pipeline/basic.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { expectExpressionProvider } from './helpers'; // this file showcases how to use testing utilities defined in helpers.js together with the kbn_tp_run_pipeline diff --git a/test/interpreter_functional/test_suites/run_pipeline/helpers.js b/test/interpreter_functional/test_suites/run_pipeline/helpers.js index 8d8f65bd8d8e6..aacdf1f615bd7 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/helpers.js +++ b/test/interpreter_functional/test_suites/run_pipeline/helpers.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; // helper for testing interpreter expressions export const expectExpressionProvider = ({ getService, updateBaselines }) => { diff --git a/test/plugin_functional/test_suites/app_plugins/app_navigation.js b/test/plugin_functional/test_suites/app_plugins/app_navigation.js index 1adcde72e1aa3..a6c5b9542f568 100644 --- a/test/plugin_functional/test_suites/app_plugins/app_navigation.js +++ b/test/plugin_functional/test_suites/app_plugins/app_navigation.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const appsMenu = getService('appsMenu'); diff --git a/test/plugin_functional/test_suites/custom_visualizations/self_changing_vis.js b/test/plugin_functional/test_suites/custom_visualizations/self_changing_vis.js index dee2515f9bd25..74519b8117b6f 100644 --- a/test/plugin_functional/test_suites/custom_visualizations/self_changing_vis.js +++ b/test/plugin_functional/test_suites/custom_visualizations/self_changing_vis.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const testSubjects = getService('testSubjects'); diff --git a/test/plugin_functional/test_suites/embedding_visualizations/embed_by_id.js b/test/plugin_functional/test_suites/embedding_visualizations/embed_by_id.js index bd0866882c1fc..dbcf859906dcc 100644 --- a/test/plugin_functional/test_suites/embedding_visualizations/embed_by_id.js +++ b/test/plugin_functional/test_suites/embedding_visualizations/embed_by_id.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { delay } from 'bluebird'; export default function ({ getService }) { diff --git a/test/plugin_functional/test_suites/panel_actions/panel_actions.js b/test/plugin_functional/test_suites/panel_actions/panel_actions.js index 0202fb1f5d534..d7152e0885157 100644 --- a/test/plugin_functional/test_suites/panel_actions/panel_actions.js +++ b/test/plugin_functional/test_suites/panel_actions/panel_actions.js @@ -17,7 +17,7 @@ * under the License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const dashboardPanelActions = getService('dashboardPanelActions'); diff --git a/test/tsconfig.json b/test/tsconfig.json index f72d03a94f26b..5df729fbde21b 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -3,8 +3,7 @@ "compilerOptions": { "types": [ "node", - "mocha", - "@kbn/test/types/expect.js" + "mocha" ] }, "include": [ diff --git a/tsconfig.json b/tsconfig.json index 59f963b038b8b..d9750b3f259d3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -53,8 +53,7 @@ "types": [ "node", "jest", - "react", - "@kbn/test/types/expect.js" + "react" ] }, "include": [ diff --git a/tslint.yaml b/tslint.yaml index c914787ec7a68..c6447271a7107 100644 --- a/tslint.yaml +++ b/tslint.yaml @@ -67,3 +67,7 @@ rules: * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + module-migration: + - true + - from: expect.js + to: '@kbn/expect' diff --git a/x-pack/common/__tests__/poller.js b/x-pack/common/__tests__/poller.js index 681a70c56280e..1e82fcc367286 100644 --- a/x-pack/common/__tests__/poller.js +++ b/x-pack/common/__tests__/poller.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { Poller } from '../poller'; diff --git a/x-pack/package.json b/x-pack/package.json index 413b9ad22be2e..2ad347a2d7284 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -27,6 +27,7 @@ "devDependencies": { "@kbn/dev-utils": "1.0.0", "@kbn/es": "1.0.0", + "@kbn/expect": "1.0.0", "@kbn/plugin-helpers": "9.0.2", "@kbn/test": "1.0.0", "@storybook/addon-actions": "^4.1.7", @@ -90,7 +91,6 @@ "enzyme-adapter-utils": "^1.10.0", "enzyme-to-json": "^3.3.4", "execa": "^1.0.0", - "expect.js": "0.3.1", "fancy-log": "^1.3.2", "fetch-mock": "7.3.0", "graphql-code-generator": "^0.13.0", diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/__tests__/markdown.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/__tests__/markdown.js index d4ea050951c9a..e1b0fe770cd3d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/__tests__/markdown.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/__tests__/markdown.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { markdown } from '../markdown'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable } from '../../common/__tests__/fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/all.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/all.js index 90558c26d5c87..3cde6599d3da2 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/all.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/all.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { all } from '../all'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/alterColumn.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/alterColumn.js index a9ad20c05c6f3..e4487b5bb4ca0 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/alterColumn.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/alterColumn.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { alterColumn } from '../alterColumn'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { emptyTable, testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/any.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/any.js index bc67aa377e49d..5c5b35fa36163 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/any.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/any.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { any } from '../any'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/as.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/as.js index 82a8d29742279..9da489fc9e4f9 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/as.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/as.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { asFn } from '../as'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/axis_config.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/axis_config.js index 1e4bbccb8ae38..06f7bca305980 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/axis_config.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/axis_config.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { axisConfig } from '../axisConfig'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable } from '../__tests__/fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/case.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/case.js index c5fd1f14e79db..37aaa96a7fa16 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/case.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/case.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { caseFn } from '../case'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/clear.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/clear.js index fc6ca6c813d28..80f3b6a4f257b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/clear.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/clear.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { clear } from '../clear'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/columns.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/columns.js index ca1e647cbe9e7..f4be4920c5737 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/columns.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/columns.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { columns } from '../columns'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { emptyTable, testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js index 2bd31f5d69ffc..26e7b83258b35 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { compare } from '../compare'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/container_style.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/container_style.js index 7daef98b0929c..77a9bef72d3e8 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/container_style.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/container_style.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { containerStyle } from '../containerStyle'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { elasticLogo } from '../../../lib/elastic_logo'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/context.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/context.js index da162dc9150b1..7d3ce308d6796 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/context.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/context.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { context } from '../context'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable, emptyTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/csv.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/csv.js index 8f79cab5577af..03bd7669063bc 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/csv.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/csv.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { csv } from '../csv'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/date.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/date.js index 94b6e7eb4f674..7f79f7cbc4638 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/date.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/date.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { date } from '../date'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/do.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/do.js index 000e614a35c98..6cb6af5405c2a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/do.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/do.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { doFn } from '../do'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/dropdown_control.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/dropdown_control.js index 437e55a197c40..0c977759b18a7 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/dropdown_control.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/dropdown_control.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { dropdownControl } from '../dropdownControl'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/eq.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/eq.js index a419dd98f3ffa..1e03c73cbcf20 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/eq.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/eq.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { eq } from '../eq'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/exactly.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/exactly.js index e9f37efd15c26..444befdcd0ffc 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/exactly.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/exactly.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { exactly } from '../exactly'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { emptyFilter } from './fixtures/test_filters'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/filterrows.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/filterrows.js index baa7096cb6324..6ab8fd58f27eb 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/filterrows.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/filterrows.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { filterrows } from '../filterrows'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/font.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/font.js index 0bd5871b03ad1..0848d7361b684 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/font.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/font.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { openSans } from '../../../../common/lib/fonts'; import { font } from '../font'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/formatdate.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/formatdate.js index d9f9169079044..bcbd5f4b5ecad 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/formatdate.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/formatdate.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { formatdate } from '../formatdate'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/formatnumber.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/formatnumber.js index b0d8a7df62f1f..c0e10f3080028 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/formatnumber.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/formatnumber.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { formatnumber } from '../formatnumber'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/getCell.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/getCell.js index 7b73dbec4df08..f780aadb4032a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/getCell.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/getCell.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getCell } from '../getCell'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { emptyTable, testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_flot_axis_config.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_flot_axis_config.js index 2a1fca38f2685..0e309f667ac8f 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_flot_axis_config.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_flot_axis_config.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getFlotAxisConfig } from '../plot/get_flot_axis_config'; import { xAxisConfig, yAxisConfig, hideAxis } from './fixtures/test_styles'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_font_spec.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_font_spec.js index 4f2fb67cd938f..91555ee0382f8 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_font_spec.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_font_spec.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { defaultSpec, getFontSpec } from '../plot/get_font_spec'; import { fontStyle } from './fixtures/test_styles'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_tick_hash.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_tick_hash.js index 02412862d9512..7ca21c792003d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_tick_hash.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/get_tick_hash.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getTickHash } from '../plot/get_tick_hash'; describe('getTickHash', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/gt.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/gt.js index ca490aa88fec7..7f0e259a5211f 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/gt.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/gt.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { gt } from '../gt'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/gte.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/gte.js index ba4f0f7a3f9b1..a6d88b2d839a7 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/gte.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/gte.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { gte } from '../gte'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/head.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/head.js index d9cd5a0743764..2822eb39ae47e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/head.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/head.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { head } from '../head'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { emptyTable, testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/if.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/if.js index aee9efc5203c2..4c95af2c40bc6 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/if.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/if.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ifFn } from '../if'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js index 304d970882bf4..0d1c80665f570 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { image } from '../image'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { elasticLogo } from '../../../lib/elastic_logo'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/lt.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/lt.js index 3597bd3805d6e..abc0f6e66641c 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/lt.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/lt.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { lt } from '../lt'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/lte.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/lte.js index e800b72c13ff5..3eeadbb62b272 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/lte.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/lte.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { lte } from '../lte'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/mapColumn.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/mapColumn.js index 87db17cf8b312..bdcdf39625549 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/mapColumn.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/mapColumn.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { mapColumn } from '../mapColumn'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable, emptyTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/math.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/math.js index f290cce865153..da5069764927c 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/math.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/math.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { math } from '../math'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { emptyTable, testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/metric.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/metric.js index 587e7fbf1f8b0..f59b0c7bf52a0 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/metric.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/metric.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { metric } from '../metric'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { fontStyle } from './fixtures/test_styles'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/neq.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/neq.js index 3d2ca7b90017c..c4abc22249dc0 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/neq.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/neq.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { neq } from '../neq'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/palette.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/palette.js index ecb3ed8b2bbd0..d3f828cfbcf0b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/palette.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/palette.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { palette } from '../palette'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { palettes } from '../../../../common/lib/palettes'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/pie.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/pie.js index 2048b6763fb25..d51c718ca4ce7 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/pie.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/pie.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { pie } from '../pie'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testPie } from './fixtures/test_pointseries'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/plot.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/plot.js index 3d6c62419ef48..fadf847135a4e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/plot.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/plot.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { plot } from '../plot'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testPlot } from './fixtures/test_pointseries'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/ply.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/ply.js index 54e33de91a47b..b22ac6df0ed37 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/ply.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/ply.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ply } from '../ply'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js index 61df4292e0254..70ff9d2c6a280 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { progress } from '../progress'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { fontStyle } from './fixtures/test_styles'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/render.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/render.js index 720242418e0a5..c29df283fdc1d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/render.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/render.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { render } from '../render'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/repeat_image.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/repeat_image.js index 0a18b7d25071e..65d17cf2d6387 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/repeat_image.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/repeat_image.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { repeatImage } from '../repeatImage'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { elasticOutline } from '../../../lib/elastic_outline'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/replace.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/replace.js index 55fcbf10d7fd7..3eea71fb1cdbd 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/replace.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/replace.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { replace } from '../replace'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/reveal_image.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/reveal_image.js index 3a3707e7c0b72..8f33f831c8346 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/reveal_image.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/reveal_image.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { revealImage } from '../revealImage'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { elasticOutline } from '../../../lib/elastic_outline'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/rounddate.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/rounddate.js index ab66ef05f4f2b..6f4402d5234f4 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/rounddate.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/rounddate.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { rounddate } from '../rounddate'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/rowCount.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/rowCount.js index c50f39f7b3084..350ffca635d85 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/rowCount.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/rowCount.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { rowCount } from '../rowCount'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { emptyTable, testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/series_style.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/series_style.js index a0de476435949..9130f0d34e452 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/series_style.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/series_style.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { seriesStyle } from '../seriesStyle'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/series_style_to_flot.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/series_style_to_flot.js index adb6b48b9b28b..e84c9fc6e6e69 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/series_style_to_flot.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/series_style_to_flot.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { seriesStyleToFlot } from '../plot/series_style_to_flot'; describe('seriesStyleToFlot', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/sort.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/sort.js index 9940be856ec91..3c927cde9ccd6 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/sort.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/sort.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { sort } from '../sort'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/staticColumn.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/staticColumn.js index 01d00a3b74bf9..d34a2fe4c3e42 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/staticColumn.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/staticColumn.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { staticColumn } from '../staticColumn'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable, emptyTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/string.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/string.js index 7961d0553644d..5fd11273df7fd 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/string.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/string.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { string } from '../string'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/switch.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/switch.js index 769b0ae8c5579..8a7b52ae87a81 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/switch.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/switch.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { switchFn } from '../switch'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/table.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/table.js index 0980f4b124f49..4ba2b3149e064 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/table.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/table.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { table } from '../table'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/tail.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/tail.js index 2e2148237df3d..05e1b2e8f91d6 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/tail.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/tail.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { tail } from '../tail'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; import { emptyTable, testTable } from './fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter.js index 70a3a007b889c..76bc2ee9ed0ff 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { timefilter } from '../timefilter'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter_control.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter_control.js index 1341f961412da..e46c9c0f19810 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter_control.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/timefilter_control.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { timefilterControl } from '../timefilterControl'; import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/demodata.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/demodata.js index 1871bc560b795..1892029395a7c 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/demodata.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/demodata.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { demodata } from '../demodata'; const nullFilter = { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/get_expression_type.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/get_expression_type.js index f22daa0a8cf51..3e621145e0685 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/get_expression_type.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/get_expression_type.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getExpressionType } from '../pointseries/lib/get_expression_type'; import { emptyTable, testTable } from '../../common/__tests__/fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/get_field_names.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/get_field_names.js index 9b3f9990d1122..2cf9693a5f159 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/get_field_names.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/get_field_names.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { parse } from 'tinymath'; import { getFieldNames } from '../pointseries/lib/get_field_names'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/is_column_reference.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/is_column_reference.js index 10951e73b301d..8e8a760be9a26 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/is_column_reference.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/is_column_reference.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isColumnReference } from '../pointseries/lib/is_column_reference'; describe('isColumnReference', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/pointseries.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/pointseries.js index c2c7fb8f4a477..f8e7c7f650b66 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/pointseries.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/__tests__/pointseries.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { pointseries } from '../pointseries'; import { emptyTable, testTable } from '../../common/__tests__/fixtures/test_tables'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js index cf1ae0ea37afc..dbc129094acff 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getFormObject } from '../get_form_object'; describe('getFormObject', () => { diff --git a/x-pack/plugins/canvas/common/lib/__tests__/autocomplete.js b/x-pack/plugins/canvas/common/lib/__tests__/autocomplete.js index 72d79adf2a030..58d689c029f6a 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/autocomplete.js +++ b/x-pack/plugins/canvas/common/lib/__tests__/autocomplete.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { functionSpecs } from '../../../__tests__/fixtures/function_specs'; import { getAutocompleteSuggestions } from '../autocomplete'; diff --git a/x-pack/plugins/canvas/common/lib/__tests__/find_in_object.js b/x-pack/plugins/canvas/common/lib/__tests__/find_in_object.js index b07cd4563a124..f3fa5ebb81a14 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/find_in_object.js +++ b/x-pack/plugins/canvas/common/lib/__tests__/find_in_object.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { findInObject } from '../find_in_object'; const findMe = { diff --git a/x-pack/plugins/canvas/common/lib/__tests__/get_colors_from_palette.js b/x-pack/plugins/canvas/common/lib/__tests__/get_colors_from_palette.js index 79824edc2e2f7..e397bda763f1a 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/get_colors_from_palette.js +++ b/x-pack/plugins/canvas/common/lib/__tests__/get_colors_from_palette.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getColorsFromPalette } from '../../lib/get_colors_from_palette'; import { grayscalePalette, diff --git a/x-pack/plugins/canvas/common/lib/__tests__/get_field_type.js b/x-pack/plugins/canvas/common/lib/__tests__/get_field_type.js index cb8f7f68a796c..974880e74e328 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/get_field_type.js +++ b/x-pack/plugins/canvas/common/lib/__tests__/get_field_type.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getFieldType } from '../get_field_type'; import { emptyTable, diff --git a/x-pack/plugins/canvas/common/lib/__tests__/get_legend_config.js b/x-pack/plugins/canvas/common/lib/__tests__/get_legend_config.js index cca2cd73d0faf..ba43db7a83677 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/get_legend_config.js +++ b/x-pack/plugins/canvas/common/lib/__tests__/get_legend_config.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLegendConfig } from '../get_legend_config'; describe('getLegendConfig', () => { diff --git a/x-pack/plugins/canvas/common/lib/__tests__/httpurl.js b/x-pack/plugins/canvas/common/lib/__tests__/httpurl.js index 5d7397ed87a50..cefe2530a01f9 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/httpurl.js +++ b/x-pack/plugins/canvas/common/lib/__tests__/httpurl.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isValidHttpUrl } from '../httpurl'; describe('httpurl.isValidHttpUrl', () => { diff --git a/x-pack/plugins/canvas/common/lib/__tests__/latest_change.js b/x-pack/plugins/canvas/common/lib/__tests__/latest_change.js index cc5c246b2c074..f3678267540bf 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/latest_change.js +++ b/x-pack/plugins/canvas/common/lib/__tests__/latest_change.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { latestChange } from '../latest_change'; describe('latestChange', () => { diff --git a/x-pack/plugins/canvas/common/lib/__tests__/pivot_object_array.js b/x-pack/plugins/canvas/common/lib/__tests__/pivot_object_array.js index 58173c4c5a872..1ef875feacdc6 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/pivot_object_array.js +++ b/x-pack/plugins/canvas/common/lib/__tests__/pivot_object_array.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { pivotObjectArray } from '../pivot_object_array'; describe('pivotObjectArray', () => { diff --git a/x-pack/plugins/canvas/common/lib/__tests__/unquote_string.js b/x-pack/plugins/canvas/common/lib/__tests__/unquote_string.js index 465338816f155..52fcabf5ae7e0 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/unquote_string.js +++ b/x-pack/plugins/canvas/common/lib/__tests__/unquote_string.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { unquoteString } from '../unquote_string'; describe('unquoteString', () => { diff --git a/x-pack/plugins/canvas/public/components/download/__tests__/download.js b/x-pack/plugins/canvas/public/components/download/__tests__/download.js index 36c3a199e6fc6..6697730b0db60 100644 --- a/x-pack/plugins/canvas/public/components/download/__tests__/download.js +++ b/x-pack/plugins/canvas/public/components/download/__tests__/download.js @@ -5,7 +5,7 @@ */ import React from 'react'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { render } from 'enzyme'; import { Download } from '../'; diff --git a/x-pack/plugins/canvas/public/components/loading/__tests__/loading.js b/x-pack/plugins/canvas/public/components/loading/__tests__/loading.js index bae592801f537..c159f478766ce 100644 --- a/x-pack/plugins/canvas/public/components/loading/__tests__/loading.js +++ b/x-pack/plugins/canvas/public/components/loading/__tests__/loading.js @@ -5,7 +5,7 @@ */ import React from 'react'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { shallow } from 'enzyme'; import { EuiLoadingSpinner, EuiIcon } from '@elastic/eui'; import { Loading } from '../loading'; diff --git a/x-pack/plugins/canvas/public/functions/__tests__/asset.js b/x-pack/plugins/canvas/public/functions/__tests__/asset.js index ea9f1d051ca61..208af754e9105 100644 --- a/x-pack/plugins/canvas/public/functions/__tests__/asset.js +++ b/x-pack/plugins/canvas/public/functions/__tests__/asset.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; import { asset } from '../asset'; diff --git a/x-pack/plugins/canvas/public/lib/__tests__/clipboard.js b/x-pack/plugins/canvas/public/lib/__tests__/clipboard.js index d940701c2e71d..c616a76d0dcc3 100644 --- a/x-pack/plugins/canvas/public/lib/__tests__/clipboard.js +++ b/x-pack/plugins/canvas/public/lib/__tests__/clipboard.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { setClipboardData, getClipboardData } from '../clipboard'; import { elements } from '../../../__tests__/fixtures/workpads'; diff --git a/x-pack/plugins/canvas/public/lib/__tests__/history_provider.js b/x-pack/plugins/canvas/public/lib/__tests__/history_provider.js index 68c45d0eb7e4b..756dd4e36e759 100644 --- a/x-pack/plugins/canvas/public/lib/__tests__/history_provider.js +++ b/x-pack/plugins/canvas/public/lib/__tests__/history_provider.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import lzString from 'lz-string'; import { historyProvider } from '../history_provider'; diff --git a/x-pack/plugins/canvas/public/lib/__tests__/modify_path.js b/x-pack/plugins/canvas/public/lib/__tests__/modify_path.js index c5d84e74a3e07..75454890f9717 100644 --- a/x-pack/plugins/canvas/public/lib/__tests__/modify_path.js +++ b/x-pack/plugins/canvas/public/lib/__tests__/modify_path.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { prepend, append } from '../modify_path'; describe('modify paths', () => { diff --git a/x-pack/plugins/canvas/public/lib/__tests__/resolved_arg.js b/x-pack/plugins/canvas/public/lib/__tests__/resolved_arg.js index 24665a11c50f5..9e582ddd1858b 100644 --- a/x-pack/plugins/canvas/public/lib/__tests__/resolved_arg.js +++ b/x-pack/plugins/canvas/public/lib/__tests__/resolved_arg.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getState, getValue, getError } from '../resolved_arg'; describe('resolved arg helper', () => { diff --git a/x-pack/plugins/canvas/public/state/actions/__tests__/elements.get_sibling_context.js b/x-pack/plugins/canvas/public/state/actions/__tests__/elements.get_sibling_context.js index a1e5418b0daf7..198ccb2ffc381 100644 --- a/x-pack/plugins/canvas/public/state/actions/__tests__/elements.get_sibling_context.js +++ b/x-pack/plugins/canvas/public/state/actions/__tests__/elements.get_sibling_context.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getSiblingContext } from '../elements'; const state = { diff --git a/x-pack/plugins/canvas/public/state/reducers/__tests__/elements.js b/x-pack/plugins/canvas/public/state/reducers/__tests__/elements.js index 0a5db91198966..e1f7509325a7a 100644 --- a/x-pack/plugins/canvas/public/state/reducers/__tests__/elements.js +++ b/x-pack/plugins/canvas/public/state/reducers/__tests__/elements.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { get } from 'lodash'; import { elementsReducer } from '../elements'; import { actionCreator } from './fixtures/action_creator'; diff --git a/x-pack/plugins/canvas/public/state/reducers/__tests__/resolved_args.js b/x-pack/plugins/canvas/public/state/reducers/__tests__/resolved_args.js index 7b8bc923a20c1..ef52a80b8960c 100644 --- a/x-pack/plugins/canvas/public/state/reducers/__tests__/resolved_args.js +++ b/x-pack/plugins/canvas/public/state/reducers/__tests__/resolved_args.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as actions from '../../actions/resolved_args'; import { flushContextAfterIndex } from '../../actions/elements'; import { resolvedArgsReducer } from '../resolved_args'; diff --git a/x-pack/plugins/canvas/public/state/selectors/__tests__/resolved_args.js b/x-pack/plugins/canvas/public/state/selectors/__tests__/resolved_args.js index 6fa3b4e35db0c..3157201927854 100644 --- a/x-pack/plugins/canvas/public/state/selectors/__tests__/resolved_args.js +++ b/x-pack/plugins/canvas/public/state/selectors/__tests__/resolved_args.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as selector from '../resolved_args'; describe('resolved args selector', () => { diff --git a/x-pack/plugins/canvas/public/state/selectors/__tests__/workpad.js b/x-pack/plugins/canvas/public/state/selectors/__tests__/workpad.js index f1ff31874935b..5cfdf726dd258 100644 --- a/x-pack/plugins/canvas/public/state/selectors/__tests__/workpad.js +++ b/x-pack/plugins/canvas/public/state/selectors/__tests__/workpad.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as selector from '../workpad'; describe('workpad selectors', () => { diff --git a/x-pack/plugins/canvas/server/usage/__tests__/collector.handle_response.js b/x-pack/plugins/canvas/server/usage/__tests__/collector.handle_response.js index 06c12ca614936..edb90f90612a2 100644 --- a/x-pack/plugins/canvas/server/usage/__tests__/collector.handle_response.js +++ b/x-pack/plugins/canvas/server/usage/__tests__/collector.handle_response.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { handleResponse } from '../collector'; import { workpads } from '../../../__tests__/fixtures/workpads'; diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_custom_error.js index 443744ccb0cc8..f9c102be7a1ff 100644 --- a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_custom_error.js +++ b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_custom_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapCustomError } from '../wrap_custom_error'; describe('wrap_custom_error', () => { diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_es_error.js index b8d59590ebf33..f3237563edb45 100644 --- a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_es_error.js +++ b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_es_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapEsError } from '../wrap_es_error'; describe('wrap_es_error', () => { diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_unknown_error.js index 6d6a336417bef..85e0b2b3033ad 100644 --- a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_unknown_error.js +++ b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_unknown_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapUnknownError } from '../wrap_unknown_error'; describe('wrap_unknown_error', () => { diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/cross_cluster_replication/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js index d50ff9480d3e4..76fdf7b36c3d0 100644 --- a/x-pack/plugins/cross_cluster_replication/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js +++ b/x-pack/plugins/cross_cluster_replication/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isEsErrorFactory } from '../is_es_error_factory'; import { set } from 'lodash'; diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/cross_cluster_replication/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index ffbbd1395a418..dc641bef91085 100644 --- a/x-pack/plugins/cross_cluster_replication/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/cross_cluster_replication/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { licensePreRoutingFactory } from '../license_pre_routing_factory'; describe('license_pre_routing_factory', () => { diff --git a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_auth_scope.js b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_auth_scope.js index d3f28a1556b8b..644d006de400e 100644 --- a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_auth_scope.js +++ b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_auth_scope.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { CONFIG_DASHBOARD_ONLY_MODE_ROLES, diff --git a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js index b8c46c9e97f15..7250293fd50b0 100644 --- a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js +++ b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Hapi from 'hapi'; import Chance from 'chance'; diff --git a/x-pack/plugins/graph/public/__tests__/workspace.js b/x-pack/plugins/graph/public/__tests__/workspace.js index 2b3fe539377a4..592872c96ee05 100644 --- a/x-pack/plugins/graph/public/__tests__/workspace.js +++ b/x-pack/plugins/graph/public/__tests__/workspace.js @@ -5,7 +5,7 @@ */ const gws = require('../graphClientWorkspace.js'); -const expect = require('expect.js'); +const expect = require('@kbn/expect'); describe('graphui-workspace', function () { describe('createWorkspace()', function () { diff --git a/x-pack/plugins/graph/server/lib/__tests__/check_license.js b/x-pack/plugins/graph/server/lib/__tests__/check_license.js index abdb1fb316bdb..c341dfbc378ca 100644 --- a/x-pack/plugins/graph/server/lib/__tests__/check_license.js +++ b/x-pack/plugins/graph/server/lib/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import sinon from 'sinon'; import { checkLicense } from '../check_license'; diff --git a/x-pack/plugins/grokdebugger/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/grokdebugger/server/lib/check_license/__tests__/check_license.js index 7d2c0d73c4421..556abf1a405b4 100644 --- a/x-pack/plugins/grokdebugger/server/lib/check_license/__tests__/check_license.js +++ b/x-pack/plugins/grokdebugger/server/lib/check_license/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { checkLicense } from '../check_license'; diff --git a/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index 9196b8b813470..5458dfa9599aa 100644 --- a/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Boom from 'boom'; import { licensePreRoutingFactory } from '../license_pre_routing_factory'; diff --git a/x-pack/plugins/grokdebugger/server/models/grokdebugger_request/__tests__/grokdebugger_request.js b/x-pack/plugins/grokdebugger/server/models/grokdebugger_request/__tests__/grokdebugger_request.js index a6bc0448a0d12..a87999873e40f 100644 --- a/x-pack/plugins/grokdebugger/server/models/grokdebugger_request/__tests__/grokdebugger_request.js +++ b/x-pack/plugins/grokdebugger/server/models/grokdebugger_request/__tests__/grokdebugger_request.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { GrokdebuggerRequest } from '../grokdebugger_request'; describe('grokdebugger_request', () => { diff --git a/x-pack/plugins/grokdebugger/server/models/grokdebugger_response/__tests__/grokdebugger_response.js b/x-pack/plugins/grokdebugger/server/models/grokdebugger_response/__tests__/grokdebugger_response.js index f483352a70d3e..b4e7eb0814bf1 100644 --- a/x-pack/plugins/grokdebugger/server/models/grokdebugger_response/__tests__/grokdebugger_response.js +++ b/x-pack/plugins/grokdebugger/server/models/grokdebugger_response/__tests__/grokdebugger_response.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { GrokdebuggerResponse } from '../grokdebugger_response'; describe('grokdebugger_response', () => { diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js index 19a7b56759269..394c2c4735c0c 100644 --- a/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js +++ b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { checkLicense } from '../check_license'; diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js index 443744ccb0cc8..f9c102be7a1ff 100644 --- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js +++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapCustomError } from '../wrap_custom_error'; describe('wrap_custom_error', () => { diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js index 394c182140000..467cc4fcdae1f 100644 --- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js +++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapEsError } from '../wrap_es_error'; describe('wrap_es_error', () => { diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js index 6d6a336417bef..85e0b2b3033ad 100644 --- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js +++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapUnknownError } from '../wrap_unknown_error'; describe('wrap_unknown_error', () => { diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js index d50ff9480d3e4..76fdf7b36c3d0 100644 --- a/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js +++ b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isEsErrorFactory } from '../is_es_error_factory'; import { set } from 'lodash'; diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index 359b3fb2ce6f4..24cbaae2b2b67 100644 --- a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { licensePreRoutingFactory } from '../license_pre_routing_factory'; describe('license_pre_routing_factory', () => { diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js index 496d15f6b32a9..e24b7e455e04d 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getSuggestionsProvider } from '../conjunction'; describe('Kuery conjunction suggestions', function () { diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/escape_kuery.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/escape_kuery.js index 9ec2086f8c599..ae43f5d7f8ca1 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/escape_kuery.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/escape_kuery.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { escapeQuotes, escapeKuery } from '../escape_kuery'; describe('Kuery escape', function () { diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js index 6535886d372c3..f95615ae40c2e 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getSuggestionsProvider } from '../field'; import indexPatternResponse from '../__fixtures__/index_pattern_response.json'; import { isFilterable } from 'ui/index_patterns/static_utils'; diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js index a9bc8e988aac5..d56601c997f81 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getSuggestionsProvider } from '../operator'; import indexPatternResponse from '../__fixtures__/index_pattern_response.json'; diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js index e7120ca428acb..d2cce4fe59282 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import fetchMock from 'fetch-mock'; import { getSuggestionsProvider } from '../value'; diff --git a/x-pack/plugins/logstash/common/lib/__tests__/get_moment.js b/x-pack/plugins/logstash/common/lib/__tests__/get_moment.js index 69ccd634ec6e7..a90099f465ccd 100755 --- a/x-pack/plugins/logstash/common/lib/__tests__/get_moment.js +++ b/x-pack/plugins/logstash/common/lib/__tests__/get_moment.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getMoment } from '../get_moment'; describe('get_moment', () => { diff --git a/x-pack/plugins/logstash/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/logstash/server/lib/check_license/__tests__/check_license.js index 449ff3a60b9e7..0a8014c1b8612 100755 --- a/x-pack/plugins/logstash/server/lib/check_license/__tests__/check_license.js +++ b/x-pack/plugins/logstash/server/lib/check_license/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { checkLicense } from '../check_license'; diff --git a/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js index 443744ccb0cc8..f9c102be7a1ff 100755 --- a/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js +++ b/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapCustomError } from '../wrap_custom_error'; describe('wrap_custom_error', () => { diff --git a/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js index f1b956bdcc3bb..4d5e0852b9e07 100755 --- a/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js +++ b/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapEsError } from '../wrap_es_error'; describe('wrap_es_error', () => { diff --git a/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js index 6d6a336417bef..85e0b2b3033ad 100755 --- a/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js +++ b/x-pack/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapUnknownError } from '../wrap_unknown_error'; describe('wrap_unknown_error', () => { diff --git a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js index 582c021892d42..5e532b68e2bcc 100755 --- a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js +++ b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { fetchAllFromScroll } from '../fetch_all_from_scroll'; import { set } from 'lodash'; diff --git a/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index c63eef750bee9..fb71aba3fa94c 100755 --- a/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { licensePreRoutingFactory } from '../license_pre_routing_factory'; describe('license_pre_routing_factory', () => { diff --git a/x-pack/plugins/logstash/server/models/cluster/__tests__/cluster.js b/x-pack/plugins/logstash/server/models/cluster/__tests__/cluster.js index 04c47389ee717..2f7af6a564b0b 100755 --- a/x-pack/plugins/logstash/server/models/cluster/__tests__/cluster.js +++ b/x-pack/plugins/logstash/server/models/cluster/__tests__/cluster.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Cluster } from '../cluster'; describe('cluster', () => { diff --git a/x-pack/plugins/logstash/server/models/pipeline/__tests__/pipeline.js b/x-pack/plugins/logstash/server/models/pipeline/__tests__/pipeline.js index bbce4d29007b2..ed95abef2e226 100755 --- a/x-pack/plugins/logstash/server/models/pipeline/__tests__/pipeline.js +++ b/x-pack/plugins/logstash/server/models/pipeline/__tests__/pipeline.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Pipeline } from '../pipeline'; describe('pipeline', () => { diff --git a/x-pack/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js b/x-pack/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js index 9bd5955dd41dc..90bbd2d7b1dff 100755 --- a/x-pack/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js +++ b/x-pack/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PipelineListItem } from '../pipeline_list_item'; describe('pipeline_list_item', () => { diff --git a/x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js b/x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js index 1403856019f8b..d966d7d5a06a4 100644 --- a/x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js +++ b/x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getSeverity, getSeverityWithLow, diff --git a/x-pack/plugins/ml/common/util/__tests__/job_utils.js b/x-pack/plugins/ml/common/util/__tests__/job_utils.js index ea53af72b0661..12711a8d02960 100644 --- a/x-pack/plugins/ml/common/util/__tests__/job_utils.js +++ b/x-pack/plugins/ml/common/util/__tests__/job_utils.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { calculateDatafeedFrequencyDefaultSeconds, isTimeSeriesViewJob, diff --git a/x-pack/plugins/ml/common/util/__tests__/parse_interval.js b/x-pack/plugins/ml/common/util/__tests__/parse_interval.js index 44d647563fb17..d06e1412b5090 100644 --- a/x-pack/plugins/ml/common/util/__tests__/parse_interval.js +++ b/x-pack/plugins/ml/common/util/__tests__/parse_interval.js @@ -7,7 +7,7 @@ import { parseInterval } from '../parse_interval'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ML parse interval util', function () { it('correctly parses an interval containing unit and value', function () { diff --git a/x-pack/plugins/ml/common/util/__tests__/string_utils.js b/x-pack/plugins/ml/common/util/__tests__/string_utils.js index 16e416af3806d..e2a791c74bd7b 100644 --- a/x-pack/plugins/ml/common/util/__tests__/string_utils.js +++ b/x-pack/plugins/ml/common/util/__tests__/string_utils.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { renderTemplate } from '../string_utils'; describe('ML - string utils', () => { diff --git a/x-pack/plugins/ml/public/components/annotations/annotations_table/__tests__/annotations_table_directive.js b/x-pack/plugins/ml/public/components/annotations/annotations_table/__tests__/annotations_table_directive.js index 2a382992fa597..d53271aba5511 100644 --- a/x-pack/plugins/ml/public/components/annotations/annotations_table/__tests__/annotations_table_directive.js +++ b/x-pack/plugins/ml/public/components/annotations/annotations_table/__tests__/annotations_table_directive.js @@ -7,7 +7,7 @@ import jobConfig from '../../../../../common/types/__mocks__/job_config_farequote'; import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { ml } from '../../../../services/ml_api_service'; diff --git a/x-pack/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js b/x-pack/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js index 817e5894211bb..a542b5284b70b 100644 --- a/x-pack/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js +++ b/x-pack/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { mlChartTooltipService } from '../chart_tooltip_service'; diff --git a/x-pack/plugins/ml/public/components/confirm_modal/__tests__/confirm_modal_controller.js b/x-pack/plugins/ml/public/components/confirm_modal/__tests__/confirm_modal_controller.js index 764b6ca2eaf06..0f7d525e19cb6 100644 --- a/x-pack/plugins/ml/public/components/confirm_modal/__tests__/confirm_modal_controller.js +++ b/x-pack/plugins/ml/public/components/confirm_modal/__tests__/confirm_modal_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const mockModalInstance = { close: function () {}, dismiss: function () {} }; diff --git a/x-pack/plugins/ml/public/components/controls/select_interval/__tests__/select_interval_directive.js b/x-pack/plugins/ml/public/components/controls/select_interval/__tests__/select_interval_directive.js index aa18b75e26d2e..67b39d9bf85fc 100644 --- a/x-pack/plugins/ml/public/components/controls/select_interval/__tests__/select_interval_directive.js +++ b/x-pack/plugins/ml/public/components/controls/select_interval/__tests__/select_interval_directive.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { interval$ } from '../select_interval'; diff --git a/x-pack/plugins/ml/public/components/form_label/__tests__/form_label.js b/x-pack/plugins/ml/public/components/form_label/__tests__/form_label.js index 756bfbae6c9de..25d76e79d8a09 100644 --- a/x-pack/plugins/ml/public/components/form_label/__tests__/form_label.js +++ b/x-pack/plugins/ml/public/components/form_label/__tests__/form_label.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ML - ', () => { let $scope; diff --git a/x-pack/plugins/ml/public/components/json_tooltip/__tests__/json_tooltip.js b/x-pack/plugins/ml/public/components/json_tooltip/__tests__/json_tooltip.js index ae0ed7f557afc..889778c644452 100644 --- a/x-pack/plugins/ml/public/components/json_tooltip/__tests__/json_tooltip.js +++ b/x-pack/plugins/ml/public/components/json_tooltip/__tests__/json_tooltip.js @@ -5,7 +5,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getTooltips } from '../tooltips'; diff --git a/x-pack/plugins/ml/public/components/kql_filter_bar/__tests__/utils.js b/x-pack/plugins/ml/public/components/kql_filter_bar/__tests__/utils.js index 512c26a5cdc8e..9d7880eaf4e72 100644 --- a/x-pack/plugins/ml/public/components/kql_filter_bar/__tests__/utils.js +++ b/x-pack/plugins/ml/public/components/kql_filter_bar/__tests__/utils.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { removeFilterFromQueryString, getQueryPattern } from '../utils'; describe('ML - KqlFilterBar utils', () => { diff --git a/x-pack/plugins/ml/public/components/loading_indicator/__tests__/loading_indicator_directive.js b/x-pack/plugins/ml/public/components/loading_indicator/__tests__/loading_indicator_directive.js index 391e5a2550475..c0d461d95cd7b 100644 --- a/x-pack/plugins/ml/public/components/loading_indicator/__tests__/loading_indicator_directive.js +++ b/x-pack/plugins/ml/public/components/loading_indicator/__tests__/loading_indicator_directive.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ML - ', () => { let $scope; diff --git a/x-pack/plugins/ml/public/components/messagebar/__tests__/messagebar.js b/x-pack/plugins/ml/public/components/messagebar/__tests__/messagebar.js index 2727d69e5ef3d..5cbcdd9b8afc2 100644 --- a/x-pack/plugins/ml/public/components/messagebar/__tests__/messagebar.js +++ b/x-pack/plugins/ml/public/components/messagebar/__tests__/messagebar.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ML - Message Bar Controller', () => { beforeEach(() => { diff --git a/x-pack/plugins/ml/public/components/rule_editor/__tests__/utils.js b/x-pack/plugins/ml/public/components/rule_editor/__tests__/utils.js index bde9ebe4df3cf..88818a3c978b3 100644 --- a/x-pack/plugins/ml/public/components/rule_editor/__tests__/utils.js +++ b/x-pack/plugins/ml/public/components/rule_editor/__tests__/utils.js @@ -5,7 +5,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isValidRule, buildRuleDescription, diff --git a/x-pack/plugins/ml/public/datavisualizer/__tests__/datavisualizer_controller.js b/x-pack/plugins/ml/public/datavisualizer/__tests__/datavisualizer_controller.js index a130512216d04..9283f82335462 100644 --- a/x-pack/plugins/ml/public/datavisualizer/__tests__/datavisualizer_controller.js +++ b/x-pack/plugins/ml/public/datavisualizer/__tests__/datavisualizer_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; // Import this way to be able to stub/mock functions later on in the tests using sinon. diff --git a/x-pack/plugins/ml/public/explorer/__tests__/explorer_controller.js b/x-pack/plugins/ml/public/explorer/__tests__/explorer_controller.js index 19fa6632c14d2..d4fe0de11ca06 100644 --- a/x-pack/plugins/ml/public/explorer/__tests__/explorer_controller.js +++ b/x-pack/plugins/ml/public/explorer/__tests__/explorer_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ML - Explorer Controller', () => { beforeEach(() => { diff --git a/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js b/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js index 582d9bac39d72..4e85bae4b1862 100644 --- a/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js +++ b/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { abbreviateWholeNumber } from '../abbreviate_whole_number'; describe('ML - abbreviateWholeNumber formatter', () => { diff --git a/x-pack/plugins/ml/public/formatters/__tests__/format_value.js b/x-pack/plugins/ml/public/formatters/__tests__/format_value.js index 69362e76ceced..ffdbdd915d3a8 100644 --- a/x-pack/plugins/ml/public/formatters/__tests__/format_value.js +++ b/x-pack/plugins/ml/public/formatters/__tests__/format_value.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment-timezone'; import { formatValue } from '../format_value'; diff --git a/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js b/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js index 9c4b1516915aa..45864ce58bf83 100644 --- a/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js +++ b/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getMetricChangeDescription } from '../metric_change_description'; diff --git a/x-pack/plugins/ml/public/formatters/__tests__/round_to_decimal_place.js b/x-pack/plugins/ml/public/formatters/__tests__/round_to_decimal_place.js index 389c53300b364..b7e63846c530f 100644 --- a/x-pack/plugins/ml/public/formatters/__tests__/round_to_decimal_place.js +++ b/x-pack/plugins/ml/public/formatters/__tests__/round_to_decimal_place.js @@ -5,7 +5,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { roundToDecimalPlace } from '../round_to_decimal_place'; describe('ML - roundToDecimalPlace formatter', () => { diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/__tests__/new_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/__tests__/new_job_controller.js index 704f1466b405a..2061066ca3dfd 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/advanced/__tests__/new_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/__tests__/new_job_controller.js @@ -6,7 +6,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ML - Advanced Job Wizard - New Job Controller', () => { beforeEach(() => { diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_filter_modal/__tests__/detector_filter_modal_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_filter_modal/__tests__/detector_filter_modal_controller.js index 8e7e31ac5afda..e712cad932005 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_filter_modal/__tests__/detector_filter_modal_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_filter_modal/__tests__/detector_filter_modal_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const mockModalInstance = { close: function () {}, dismiss: function () {} }; diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_modal/__tests__/detector_modal_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_modal/__tests__/detector_modal_controller.js index 235a8ba321d4c..002050e0413f6 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_modal/__tests__/detector_modal_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_modal/__tests__/detector_modal_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const mockModalInstance = { close: function () {}, dismiss: function () {} }; diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/save_status_modal/__tests__/save_status_modal_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/save_status_modal/__tests__/save_status_modal_controller.js index 97411067f41e1..a86202f546c63 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/advanced/save_status_modal/__tests__/save_status_modal_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/save_status_modal/__tests__/save_status_modal_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const mockModalInstance = { close: function () { }, dismiss: function () { } }; diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/__tests__/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/__tests__/create_job_controller.js index 448d1bfa600dd..12ed469ab6104 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/__tests__/create_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/__tests__/create_job_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; // Import this way to be able to stub/mock functions later on in the tests using sinon. diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/__tests__/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/__tests__/create_job_controller.js index 430be2c927376..de0d4860184e6 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/__tests__/create_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/__tests__/create_job_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; // Import this way to be able to stub/mock functions later on in the tests using sinon. diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/__tests__/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/__tests__/create_job_controller.js index 2ea1913461ca7..06c6b90323cf0 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/__tests__/create_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/__tests__/create_job_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ML - Recognize Wizard - Create Job Controller', () => { diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/__tests__/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/__tests__/create_job_controller.js index ea7622a08af2c..930f6756eb069 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/__tests__/create_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/__tests__/create_job_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; // Import this way to be able to stub/mock functions later on in the tests using sinon. diff --git a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/__tests__/index_or_search_controller.js b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/__tests__/index_or_search_controller.js index d06a045b61479..6e277d24908f9 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/__tests__/index_or_search_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/__tests__/index_or_search_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ML - Index Or Search Controller', () => { beforeEach(() => { diff --git a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/__tests__/job_type_controller.js b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/__tests__/job_type_controller.js index 33500fd199512..f8fd13b2ae36e 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/__tests__/job_type_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/__tests__/job_type_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; // Import this way to be able to stub/mock functions later on in the tests using sinon. diff --git a/x-pack/plugins/ml/public/license/__tests__/check_license.js b/x-pack/plugins/ml/public/license/__tests__/check_license.js index 92dd5d27db61e..b65b5fa246d92 100644 --- a/x-pack/plugins/ml/public/license/__tests__/check_license.js +++ b/x-pack/plugins/ml/public/license/__tests__/check_license.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { xpackFeatureProvider, } from '../check_license'; diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseries_chart_directive.js b/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseries_chart_directive.js index 19e68e6cbcca9..9ee71c676c6c6 100644 --- a/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseries_chart_directive.js +++ b/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseries_chart_directive.js @@ -5,7 +5,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { TimeseriesChart } from '../components/timeseries_chart/timeseries_chart'; diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseriesexplorer_controller.js b/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseriesexplorer_controller.js index 6c3bb0a9a3252..42510c5a30fd1 100644 --- a/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseriesexplorer_controller.js +++ b/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseriesexplorer_controller.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('ML - Time Series Explorer Controller', () => { beforeEach(() => { diff --git a/x-pack/plugins/ml/public/util/__tests__/app_state_utils.js b/x-pack/plugins/ml/public/util/__tests__/app_state_utils.js index 2b0224ff112bd..3653d23464b64 100644 --- a/x-pack/plugins/ml/public/util/__tests__/app_state_utils.js +++ b/x-pack/plugins/ml/public/util/__tests__/app_state_utils.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { BehaviorSubject } from 'rxjs'; diff --git a/x-pack/plugins/ml/public/util/__tests__/chart_utils.js b/x-pack/plugins/ml/public/util/__tests__/chart_utils.js index 979615f2778be..0949605e9599d 100644 --- a/x-pack/plugins/ml/public/util/__tests__/chart_utils.js +++ b/x-pack/plugins/ml/public/util/__tests__/chart_utils.js @@ -8,7 +8,7 @@ import $ from 'jquery'; import d3 from 'd3'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { chartLimits, filterAxisLabels, diff --git a/x-pack/plugins/ml/public/util/__tests__/custom_url_utils.js b/x-pack/plugins/ml/public/util/__tests__/custom_url_utils.js index 9d7537ec23157..2081fbcb81380 100644 --- a/x-pack/plugins/ml/public/util/__tests__/custom_url_utils.js +++ b/x-pack/plugins/ml/public/util/__tests__/custom_url_utils.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { replaceTokensInUrlValue, getUrlForRecord, diff --git a/x-pack/plugins/ml/public/util/__tests__/field_types_utils.js b/x-pack/plugins/ml/public/util/__tests__/field_types_utils.js index 80426d1005aa2..c04545be05b35 100644 --- a/x-pack/plugins/ml/public/util/__tests__/field_types_utils.js +++ b/x-pack/plugins/ml/public/util/__tests__/field_types_utils.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ML_JOB_FIELD_TYPES, KBN_FIELD_TYPES } from 'plugins/ml/../common/constants/field_types'; import { kbnTypeToMLJobType } from 'plugins/ml/util/field_types_utils'; diff --git a/x-pack/plugins/ml/public/util/__tests__/ml_time_buckets.js b/x-pack/plugins/ml/public/util/__tests__/ml_time_buckets.js index 57069994ef91c..c0ac9487a1ff0 100644 --- a/x-pack/plugins/ml/public/util/__tests__/ml_time_buckets.js +++ b/x-pack/plugins/ml/public/util/__tests__/ml_time_buckets.js @@ -7,7 +7,7 @@ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { IntervalHelperProvider, diff --git a/x-pack/plugins/ml/public/util/__tests__/string_utils.js b/x-pack/plugins/ml/public/util/__tests__/string_utils.js index e8d4d5645d183..bdf467a9399a4 100644 --- a/x-pack/plugins/ml/public/util/__tests__/string_utils.js +++ b/x-pack/plugins/ml/public/util/__tests__/string_utils.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { replaceStringTokens, detectorToString, diff --git a/x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js b/x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js index dd2ade261f0bf..87ab4573c509d 100644 --- a/x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js +++ b/x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { elasticsearchJsPlugin } from '../elasticsearch_ml'; diff --git a/x-pack/plugins/ml/server/lib/__tests__/query_utils.js b/x-pack/plugins/ml/server/lib/__tests__/query_utils.js index 1a936bdf96558..671bbf1a94875 100644 --- a/x-pack/plugins/ml/server/lib/__tests__/query_utils.js +++ b/x-pack/plugins/ml/server/lib/__tests__/query_utils.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { buildBaseFilterCriteria, buildSamplerAggregation, diff --git a/x-pack/plugins/ml/server/lib/__tests__/security_utils.js b/x-pack/plugins/ml/server/lib/__tests__/security_utils.js index fbcd3ee281a4b..073b6c3c50b85 100644 --- a/x-pack/plugins/ml/server/lib/__tests__/security_utils.js +++ b/x-pack/plugins/ml/server/lib/__tests__/security_utils.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isSecurityDisabled } from '../security_utils'; diff --git a/x-pack/plugins/ml/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/ml/server/lib/check_license/__tests__/check_license.js index 8ed3158e9b640..f65b9c98be8e3 100644 --- a/x-pack/plugins/ml/server/lib/check_license/__tests__/check_license.js +++ b/x-pack/plugins/ml/server/lib/check_license/__tests__/check_license.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { set } from 'lodash'; import { checkLicense, isBasicLicense } from '../check_license'; diff --git a/x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js b/x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js index 06a937ed68acc..7b52ed9000e54 100644 --- a/x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js +++ b/x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js @@ -7,7 +7,7 @@ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { estimateBucketSpanFactory } from '../bucket_span_estimator'; // Mock callWithRequest with the ability to simulate returning different diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js index 70f338f719270..6747743676f7d 100644 --- a/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js +++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { validateJob } from '../job_validation'; // mock callWithRequest diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js index 7253f393b2cd9..30bced32688fb 100644 --- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js +++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { validateBucketSpan } from '../validate_bucket_span'; import { SKIP_BUCKET_SPAN_ESTIMATION } from '../../../../common/constants/validation'; diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js index aa48d9f8df4ec..876b4542f688c 100644 --- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js +++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js @@ -7,7 +7,7 @@ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { validateCardinality } from '../validate_cardinality'; import mockFareQuoteCardinality from './mock_farequote_cardinality'; diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js index 4d4b4e0ebeed9..38a1c5731b3bb 100644 --- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js +++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { validateInfluencers } from '../validate_influencers'; describe('ML - validateInfluencers', () => { diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js index da65d5928d81d..2184445481eb1 100644 --- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js +++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js @@ -6,7 +6,7 @@ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { validateModelMemoryLimit } from '../validate_model_memory_limit'; describe('ML - validateModelMemoryLimit', () => { diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js index f8a4bb2c9da06..17297d6c863be 100644 --- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js +++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js @@ -7,7 +7,7 @@ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isValidTimeField, validateTimeRange } from '../validate_time_range'; import mockTimeField from './mock_time_field'; diff --git a/x-pack/plugins/monitoring/__tests__/deprecations.js b/x-pack/plugins/monitoring/__tests__/deprecations.js index 2bc46bbe99742..9e444651d4cb8 100644 --- a/x-pack/plugins/monitoring/__tests__/deprecations.js +++ b/x-pack/plugins/monitoring/__tests__/deprecations.js @@ -5,7 +5,7 @@ */ import { noop } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { deprecations as deprecationsModule } from '../deprecations'; import sinon from 'sinon'; diff --git a/x-pack/plugins/monitoring/common/__tests__/format_timestamp_to_duration.js b/x-pack/plugins/monitoring/common/__tests__/format_timestamp_to_duration.js index 1ff2f1b7a7e72..6a44693418091 100644 --- a/x-pack/plugins/monitoring/common/__tests__/format_timestamp_to_duration.js +++ b/x-pack/plugins/monitoring/common/__tests__/format_timestamp_to_duration.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { formatTimestampToDuration } from '../format_timestamp_to_duration'; import { CALCULATE_DURATION_SINCE, CALCULATE_DURATION_UNTIL } from '../constants'; diff --git a/x-pack/plugins/monitoring/public/components/alerts/__tests__/map_severity.js b/x-pack/plugins/monitoring/public/components/alerts/__tests__/map_severity.js index 13734f1d96f2b..c2f1ef703846c 100644 --- a/x-pack/plugins/monitoring/public/components/alerts/__tests__/map_severity.js +++ b/x-pack/plugins/monitoring/public/components/alerts/__tests__/map_severity.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { mapSeverity } from '../map_severity'; describe('mapSeverity', () => { diff --git a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_color.js b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_color.js index 900c19ec8f76d..7b70f1d1fb224 100644 --- a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_color.js +++ b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_color.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getColor } from '../get_color'; describe('getColors', function () { diff --git a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_last_value.js b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_last_value.js index 7f81cc3c0e8b6..97f77882631cf 100644 --- a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_last_value.js +++ b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_last_value.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLastValue } from '../get_last_value'; describe('monitoringChartGetLastValue', function () { diff --git a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_title.js b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_title.js index e981924060a79..20c1c1303d157 100644 --- a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_title.js +++ b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_title.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getTitle } from '../get_title'; describe('getTitle', function () { diff --git a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_values_for_legend.js b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_values_for_legend.js index 0f2e566212086..1338d40470ed4 100644 --- a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_values_for_legend.js +++ b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_values_for_legend.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { findIndexByX, getValuesByX, getValuesForSeriesIndex } from '../get_values_for_legend'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/config.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/config.js index 887e7fd678fdc..82814428a8006 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/config.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/config.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { Config } from '../config'; import { Graph } from '../graph'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/pipeline_state.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/pipeline_state.js index 1a734debc21ec..ae0c88da39cd7 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/pipeline_state.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/pipeline_state.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { PipelineState } from '../pipeline_state'; import { Config } from '../config'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/boolean_edge.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/boolean_edge.js index a1abcf6385f7e..3d1979c42ef82 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/boolean_edge.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/boolean_edge.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { BooleanEdge } from '../boolean_edge'; import { Edge } from '../edge'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge.js index 00105ce32703d..db8f2446a8c4a 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Edge } from '../edge'; describe('Edge', () => { diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge_factory.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge_factory.js index cb9b831f4e351..e206d080d358c 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge_factory.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { edgeFactory } from '../edge_factory'; import { Edge } from '../edge'; import { BooleanEdge } from '../boolean_edge'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/if_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/if_vertex.js index 4b98217e1817d..cc4bb419f0f2b 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/if_vertex.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/if_vertex.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { IfVertex } from '../if_vertex'; import { Vertex } from '../vertex'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/index.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/index.js index 4844ef90d1c60..0c0a014efdc93 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/index.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/index.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Graph } from '../'; import { Vertex } from '../vertex'; import { PluginVertex } from '../plugin_vertex'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js index 45d4789b73b39..8d9ccc17c2829 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Vertex } from '../vertex'; import { PluginVertex, diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/queue_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/queue_vertex.js index eb091e6bdf683..997306f52cc59 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/queue_vertex.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/queue_vertex.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { QueueVertex } from '../queue_vertex'; import { Vertex } from '../vertex'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex.js index bc29533affd6a..3c2a68ad67cc8 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Graph } from '../'; describe('Vertex', () => { diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex_factory.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex_factory.js index 5cb914a5e4210..cbfa070fe2012 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex_factory.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { vertexFactory } from '../vertex_factory'; import { PluginVertex } from '../plugin_vertex'; import { IfVertex } from '../if_vertex'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js index a4347f508a776..1f2d68ba5ee5f 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { IfStatement } from '../if_statement'; import { PluginVertex } from '../../graph/plugin_vertex'; import { IfElement } from '../../list/if_element'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/make_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/make_statement.js index eb5754169d006..c1794852d3421 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/make_statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/make_statement.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { makeStatement } from '../make_statement'; import { PluginVertex } from '../../graph/plugin_vertex'; import { IfVertex } from '../../graph/if_vertex'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js index b8c835b9bd4be..7f96298b1530a 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Pipeline } from '../'; import { Graph } from '../../graph'; import { IfStatement } from '../if_statement'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js index eafde6839eda2..3bbce82b3f022 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { PluginStatement } from '../plugin_statement'; describe('PluginStatement class', () => { diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js index 4f70604614864..7288065e282e1 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Queue } from '../queue'; describe('Queue class', () => { diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js index f695bf36d2a15..e2c0904a0938c 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Statement } from '../statement'; describe('Statement class', () => { diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/utils.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/utils.js index 53c7a1a3d0f24..fc50c3b9dfedb 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/utils.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/utils.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isVertexPipelineStage } from '../utils'; describe('Utils', () => { diff --git a/x-pack/plugins/monitoring/public/directives/main/__tests__/monitoring_main_controller.js b/x-pack/plugins/monitoring/public/directives/main/__tests__/monitoring_main_controller.js index 98a107d6e25ce..927387b42e1b7 100644 --- a/x-pack/plugins/monitoring/public/directives/main/__tests__/monitoring_main_controller.js +++ b/x-pack/plugins/monitoring/public/directives/main/__tests__/monitoring_main_controller.js @@ -5,7 +5,7 @@ */ import { noop } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { MonitoringMainController } from '../'; const getMockLicenseService = (options) => ({ mlIsSupported: () => options.mlIsSupported }); diff --git a/x-pack/plugins/monitoring/public/lib/__tests__/format_number.js b/x-pack/plugins/monitoring/public/lib/__tests__/format_number.js index 209207b52db47..e26e637c7a39b 100644 --- a/x-pack/plugins/monitoring/public/lib/__tests__/format_number.js +++ b/x-pack/plugins/monitoring/public/lib/__tests__/format_number.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { formatNumber, formatBytesUsage } from '../format_number'; diff --git a/x-pack/plugins/monitoring/public/lib/logstash/__tests__/pipelines.js b/x-pack/plugins/monitoring/public/lib/logstash/__tests__/pipelines.js index 7013db3d93568..bb914379aa114 100644 --- a/x-pack/plugins/monitoring/public/lib/logstash/__tests__/pipelines.js +++ b/x-pack/plugins/monitoring/public/lib/logstash/__tests__/pipelines.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isPipelineMonitoringSupportedInVersion } from '../pipelines'; describe('pipelines', () => { diff --git a/x-pack/plugins/monitoring/public/services/__tests__/breadcrumbs.js b/x-pack/plugins/monitoring/public/services/__tests__/breadcrumbs.js index 6943d6f4e068f..547505c0d5fef 100644 --- a/x-pack/plugins/monitoring/public/services/__tests__/breadcrumbs.js +++ b/x-pack/plugins/monitoring/public/services/__tests__/breadcrumbs.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { breadcrumbsProvider } from '../breadcrumbs_provider'; import { MonitoringMainController } from 'plugins/monitoring/directives/main'; diff --git a/x-pack/plugins/monitoring/public/services/__tests__/executor_provider.js b/x-pack/plugins/monitoring/public/services/__tests__/executor_provider.js index 805fac434bd60..36ab9431058eb 100644 --- a/x-pack/plugins/monitoring/public/services/__tests__/executor_provider.js +++ b/x-pack/plugins/monitoring/public/services/__tests__/executor_provider.js @@ -5,7 +5,7 @@ */ import ngMock from 'ng_mock'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { executorProvider } from '../executor_provider'; import Promise from 'bluebird'; diff --git a/x-pack/plugins/monitoring/public/views/__tests__/base_controller.js b/x-pack/plugins/monitoring/public/views/__tests__/base_controller.js index b10e278728794..ed9899183463c 100644 --- a/x-pack/plugins/monitoring/public/views/__tests__/base_controller.js +++ b/x-pack/plugins/monitoring/public/views/__tests__/base_controller.js @@ -5,7 +5,7 @@ */ import { spy, stub } from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { MonitoringViewBaseController } from '../'; import { timefilter } from 'ui/timefilter'; diff --git a/x-pack/plugins/monitoring/public/views/__tests__/base_table_controller.js b/x-pack/plugins/monitoring/public/views/__tests__/base_table_controller.js index 8614fa90a6af2..5c2791d781f4d 100644 --- a/x-pack/plugins/monitoring/public/views/__tests__/base_table_controller.js +++ b/x-pack/plugins/monitoring/public/views/__tests__/base_table_controller.js @@ -5,7 +5,7 @@ */ import { spy, stub } from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { MonitoringViewBaseTableController } from '../'; describe('MonitoringViewBaseTableController', function () { diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/aws.js b/x-pack/plugins/monitoring/server/cloud/__tests__/aws.js index 37e0c5531ea0d..4339d0fe3df95 100644 --- a/x-pack/plugins/monitoring/server/cloud/__tests__/aws.js +++ b/x-pack/plugins/monitoring/server/cloud/__tests__/aws.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { AWS, AWSCloudService } from '../aws'; describe('AWS', () => { diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/azure.js b/x-pack/plugins/monitoring/server/cloud/__tests__/azure.js index 4e6efe9463b53..cb5251f7844f9 100644 --- a/x-pack/plugins/monitoring/server/cloud/__tests__/azure.js +++ b/x-pack/plugins/monitoring/server/cloud/__tests__/azure.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { AZURE } from '../azure'; describe('Azure', () => { diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_detector.js b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_detector.js index 19e49bec43c8d..f290f789a319b 100644 --- a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_detector.js +++ b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_detector.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { CloudDetector } from '../cloud_detector'; describe('CloudDetector', () => { diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_response.js b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_response.js index a8cb5c8949c64..e0f31615ed156 100644 --- a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_response.js +++ b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_response.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { CloudServiceResponse } from '../cloud_response'; describe('CloudServiceResponse', () => { diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_service.js b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_service.js index 34d47d24c51e1..72c40b0a29b83 100644 --- a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_service.js +++ b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_service.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { CloudService } from '../cloud_service'; import { CloudServiceResponse } from '../cloud_response'; diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_services.js b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_services.js index 99c5a0845971d..e1139db313e92 100644 --- a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_services.js +++ b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_services.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { CLOUD_SERVICES } from '../cloud_services'; import { AWS } from '../aws'; import { AZURE } from '../azure'; diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/gcp.js b/x-pack/plugins/monitoring/server/cloud/__tests__/gcp.js index 467ea8b5ff0cd..88b9e9e3e1c34 100644 --- a/x-pack/plugins/monitoring/server/cloud/__tests__/gcp.js +++ b/x-pack/plugins/monitoring/server/cloud/__tests__/gcp.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { GCP } from '../gcp'; describe('GCP', () => { diff --git a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_cluster_search.js b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_cluster_search.js index 1b7d9a0f58bf7..b790aba05351f 100644 --- a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_cluster_search.js +++ b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_cluster_search.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { createStubs } from './fixtures/create_stubs'; import { alertsClusterSearch } from '../alerts_cluster_search'; diff --git a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_clusters_aggregation.js b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_clusters_aggregation.js index f209a5f177895..8af04a4bdb7be 100644 --- a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_clusters_aggregation.js +++ b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_clusters_aggregation.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { merge } from 'lodash'; import { createStubs } from './fixtures/create_stubs'; diff --git a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/check_license.js b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/check_license.js index df3876367b181..ec18d85752a61 100644 --- a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/check_license.js +++ b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/check_license.js @@ -5,7 +5,7 @@ */ import { checkLicense, checkLicenseGenerator } from '../check_license'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; describe('Monitoring Check License', () => { diff --git a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/verify_monitoring_license.js b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/verify_monitoring_license.js index 86902c6400adc..c70c298bf359a 100644 --- a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/verify_monitoring_license.js +++ b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/verify_monitoring_license.js @@ -5,7 +5,7 @@ */ import { verifyMonitoringLicense } from '../verify_monitoring_license'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; describe('Monitoring Verify License', () => { diff --git a/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js b/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js index 6ebd3fb7fd050..bc2afc7c25e19 100644 --- a/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js +++ b/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { get, noop } from 'lodash'; import { exposeClient, hasMonitoringCluster } from '../instantiate_client'; diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js b/x-pack/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js index 6f7b6b3383538..6c034ddac6261 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js @@ -6,7 +6,7 @@ import { noop } from 'lodash'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { BulkUploader } from '../bulk_uploader'; const FETCH_INTERVAL = 300; diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/check_for_email_value.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/check_for_email_value.js index 4189903684a9b..9823fd603221b 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/check_for_email_value.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/check_for_email_value.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { checkForEmailValue } from '../get_settings_collector'; describe('getSettingsCollector / checkForEmailValue', () => { diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_default_admin_email.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_default_admin_email.js index 0d32c1d479853..083e6de3599ac 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_default_admin_email.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_default_admin_email.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { set } from 'lodash'; diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js index 61b1e6a673d93..a97a3e28564f1 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js @@ -5,7 +5,7 @@ */ import { EventRoller } from '../event_roller'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; const events = [ { diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_requests.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_requests.js index 6fb1392830383..a5baeb452928c 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_requests.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_requests.js @@ -6,7 +6,7 @@ import _ from 'lodash'; import { mapRequests } from '../map_requests'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('Map requests', () => { it('flatten ports', () => { diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_response_times.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_response_times.js index 224b948732f07..15c987ec33264 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_response_times.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_response_times.js @@ -6,7 +6,7 @@ import { isEqual } from 'lodash'; import { mapResponseTimes } from '../map_response_times'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('Map response times', () => { it('flatten ports', () => { diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_auto.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_auto.js index 50bcac815045c..879f42f787970 100644 --- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_auto.js +++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_auto.js @@ -5,7 +5,7 @@ */ import { calculateAuto } from '../calculate_auto.js'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; import moment from 'moment'; diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_availabiilty.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_availabiilty.js index fb8193e6afcd2..3f70db5124fcb 100644 --- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_availabiilty.js +++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_availabiilty.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { calculateAvailability } from '../calculate_availability'; diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_overall_status.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_overall_status.js index 8019c3f30977c..88c84a08541b0 100644 --- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_overall_status.js +++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_overall_status.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { calculateOverallStatus } from '../calculate_overall_status'; describe('Calculate Kibana Cluster Helath', () => { diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_rate.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_rate.js index c9fac06fac7d5..3dc8808d16995 100644 --- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_rate.js +++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_rate.js @@ -5,7 +5,7 @@ */ import { calculateRate } from '../calculate_rate'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('Calculate Rate', () => { it('returns null when all fields are undefined', () => { diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_timeseries_interval.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_timeseries_interval.js index 8c2cf3c97aa10..3c4061490ebc2 100644 --- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_timeseries_interval.js +++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_timeseries_interval.js @@ -5,7 +5,7 @@ */ import moment from 'moment'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { calculateTimeseriesInterval } from '../calculate_timeseries_interval'; describe('calculateTimeseriesInterval', () => { diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/ccs_utils.js b/x-pack/plugins/monitoring/server/lib/__tests__/ccs_utils.js index e2aa07ad78ee1..d17177102dbf6 100644 --- a/x-pack/plugins/monitoring/server/lib/__tests__/ccs_utils.js +++ b/x-pack/plugins/monitoring/server/lib/__tests__/ccs_utils.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { parseCrossClusterPrefix, prefixIndexPattern } from '../ccs_utils'; diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/create_query.js b/x-pack/plugins/monitoring/server/lib/__tests__/create_query.js index 8ad0e4e5a953e..cc064c4688f85 100644 --- a/x-pack/plugins/monitoring/server/lib/__tests__/create_query.js +++ b/x-pack/plugins/monitoring/server/lib/__tests__/create_query.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { MissingRequiredError } from '../error_missing_required'; import { ElasticsearchMetric } from '../metrics'; diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/process_version_string.js b/x-pack/plugins/monitoring/server/lib/__tests__/process_version_string.js index 14f6870331db1..729e43d2f0c76 100644 --- a/x-pack/plugins/monitoring/server/lib/__tests__/process_version_string.js +++ b/x-pack/plugins/monitoring/server/lib/__tests__/process_version_string.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { normalizeVersionString } from '../normalize_version_string'; describe('Normalizing Version String', () => { diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/create_beats_query.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/create_beats_query.js index 0e6c8ba53aa23..d4b47070c80a7 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/create_beats_query.js +++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/create_beats_query.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createBeatsQuery } from '../create_beats_query'; describe('createBeatsQuery', () => { diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beat_summary.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beat_summary.js index 8cf25533178b9..fc5124b7d304a 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beat_summary.js +++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beat_summary.js @@ -5,7 +5,7 @@ */ import { handleResponse } from '../get_beat_summary'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('get_beat_summary', () => { it('Handles empty aggregation', () => { diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats.js index bbe9de2da5eb1..73b1bf77b3e0b 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats.js +++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats.js @@ -5,7 +5,7 @@ */ import { handleResponse } from '../get_beats'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('beats/get_beats', () => { it('Handles empty response', () => { diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats_for_clusters.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats_for_clusters.js index 2a77e2825a11e..9fa13b71637a4 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats_for_clusters.js +++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats_for_clusters.js @@ -5,7 +5,7 @@ */ import { handleResponse } from '../get_beats_for_clusters'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('get_beats_for_clusters', () => { it('Handles empty aggregation', () => { diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_latest_stats.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_latest_stats.js index ec21e1865224e..39b85baf7311c 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_latest_stats.js +++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_latest_stats.js @@ -5,7 +5,7 @@ */ import { handleResponse } from '../get_latest_stats'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('beats/get_latest_stats', () => { it('Handle empty response', () => { diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_stats.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_stats.js index 857259dd4b232..bf47aa1a2a562 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_stats.js +++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_stats.js @@ -5,7 +5,7 @@ */ import { handleResponse } from '../get_stats'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('beats/get_stats', () => { it('Handle empty response', () => { diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/flag_supported_clusters.js b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/flag_supported_clusters.js index b5358a1f54787..78c98ba05b8af 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/flag_supported_clusters.js +++ b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/flag_supported_clusters.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { flagSupportedClusters } from '../flag_supported_clusters'; diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_cluster_status.js b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_cluster_status.js index e6df2396ea34b..87f61a0ba87c7 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_cluster_status.js +++ b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_cluster_status.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getClusterStatus } from '../get_cluster_status'; let clusterStats = {}; diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_state.js b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_state.js index 3c5f8d2822df8..0b7dabeba72d8 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_state.js +++ b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_state.js @@ -5,7 +5,7 @@ */ import { handleResponse } from '../get_clusters_state'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { set } from 'lodash'; diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_stats.js b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_stats.js index cd9098a290208..e4755e704bf90 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_stats.js +++ b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_stats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { handleClusterStats } from '../get_clusters_stats'; describe('handleClusterStats', () => { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_last_recovery.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_last_recovery.js index 7bec0eacd964e..bd867a7475f16 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_last_recovery.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_last_recovery.js @@ -5,7 +5,7 @@ */ import { handleLastRecoveries, filterOldShardActivity } from '../get_last_recovery'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('get_last_recovery', () => { // Note: times are from the epoch! diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_ml_jobs.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_ml_jobs.js index b661f11a27207..f97b56d538a8a 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_ml_jobs.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_ml_jobs.js @@ -5,7 +5,7 @@ */ import { set } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { handleResponse } from '../get_ml_jobs'; describe('Get ML Jobs', () => { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_index_summary.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_index_summary.js index 1f395a746420c..114984c3f6d71 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_index_summary.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_index_summary.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { handleResponse } from '../get_index_summary'; describe('get_index_summary handleResponse', () => { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js index fbe84b9e3d09a..5c1e4c84898f5 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js @@ -5,7 +5,7 @@ */ import { handleResponse } from '../get_indices'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('Get Elasticsearch Indices', () => { it('handle an empty response', () => { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/calculate_node_type.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/calculate_node_type.js index 5d3de396d935a..b9adcb725f0b8 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/calculate_node_type.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/calculate_node_type.js @@ -5,7 +5,7 @@ */ import { set } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { calculateNodeType } from '../calculate_node_type.js'; const masterNodeId = 'def456'; diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js index 22e41a02eef86..40904aac2cde0 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { handleResponse } from '../get_node_summary'; describe('Elasticsearch Node Summary get_node_summary handleResponse', () => { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_type_class_label.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_type_class_label.js index c149c6e3100e9..4c21391a9ae62 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_type_class_label.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_type_class_label.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getNodeTypeClassLabel } from '../get_node_type_class_label'; describe('Node Type and Label', () => { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/lookups.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/lookups.js index b16f857acdb9a..a8c0f483ec1fa 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/lookups.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/lookups.js @@ -5,7 +5,7 @@ */ import { nodeTypeClass, nodeTypeLabel } from '../lookups'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; describe('Node Types Lookups', () => { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/get_shard_stats.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/get_shard_stats.js index 043c87877e34f..299dc0f61a41b 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/get_shard_stats.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/get_shard_stats.js @@ -5,7 +5,7 @@ */ import { cloneDeep } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { handleResponse } from '../get_shard_stats'; import { shardStatsFixture, clusterFixture } from './fixtures'; diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/normalize_shard_objects.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/normalize_shard_objects.js index 6ec0114742af8..a615a2859a7b3 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/normalize_shard_objects.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/normalize_shard_objects.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { normalizeIndexShards, normalizeNodeShards } from '../normalize_shard_objects'; function getIndexShardBucket(indexName) { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/cluster.js b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/cluster.js index e464ea323ca75..2f52f83002553 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/cluster.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/cluster.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { checkClusterSettings } from '../'; describe('Elasticsearch Cluster Settings', () => { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/find_reason.js b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/find_reason.js index e5e93d5f475f1..b3515c4c0c0a0 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/find_reason.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/find_reason.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { findReason } from '../find_reason'; describe('Elasticsearch Settings Find Reason for No Data', () => { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/nodes.js b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/nodes.js index 4d41a9b541a23..b0914bbc9861a 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/nodes.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/nodes.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { checkNodesSettings } from '../'; describe('Elasticsearch Nodes Settings', () => { diff --git a/x-pack/plugins/monitoring/server/lib/errors/__tests__/auth_errors.js b/x-pack/plugins/monitoring/server/lib/errors/__tests__/auth_errors.js index 12d3b3f99013a..3b25aa752b483 100644 --- a/x-pack/plugins/monitoring/server/lib/errors/__tests__/auth_errors.js +++ b/x-pack/plugins/monitoring/server/lib/errors/__tests__/auth_errors.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { errors } from 'elasticsearch'; import { forbidden, unauthorized } from 'boom'; import { isAuthError, handleAuthError } from '../auth_errors'; diff --git a/x-pack/plugins/monitoring/server/lib/errors/__tests__/known_errors.js b/x-pack/plugins/monitoring/server/lib/errors/__tests__/known_errors.js index 73a0e0f007745..c2b21f354abf1 100644 --- a/x-pack/plugins/monitoring/server/lib/errors/__tests__/known_errors.js +++ b/x-pack/plugins/monitoring/server/lib/errors/__tests__/known_errors.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { errors } from 'elasticsearch'; import { isKnownError, handleKnownError } from '../known_errors'; diff --git a/x-pack/plugins/monitoring/server/lib/kibana/__tests__/get_kibana_info.js b/x-pack/plugins/monitoring/server/lib/kibana/__tests__/get_kibana_info.js index d84d163c5c11e..4d8a63308d26a 100644 --- a/x-pack/plugins/monitoring/server/lib/kibana/__tests__/get_kibana_info.js +++ b/x-pack/plugins/monitoring/server/lib/kibana/__tests__/get_kibana_info.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { handleResponse } from '../get_kibana_info'; diff --git a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_node_info.js b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_node_info.js index 5ecfb0a902f8b..2cf407bfea7bd 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_node_info.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_node_info.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { handleResponse } from '../get_node_info'; diff --git a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js index 97a4610a8831f..f0e81eb63dddc 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { _vertexStats, _enrichStateWithStatsAggregation diff --git a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipelines.js b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipelines.js index 6aefd1c0b88be..47735e08c470a 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipelines.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipelines.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { _handleResponse, processPipelinesAPIResponse } from '../get_pipelines'; diff --git a/x-pack/plugins/remote_clusters/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/remote_clusters/server/lib/check_license/__tests__/check_license.js index 19a7b56759269..394c2c4735c0c 100644 --- a/x-pack/plugins/remote_clusters/server/lib/check_license/__tests__/check_license.js +++ b/x-pack/plugins/remote_clusters/server/lib/check_license/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { checkLicense } from '../check_license'; diff --git a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_custom_error.js index 443744ccb0cc8..f9c102be7a1ff 100644 --- a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_custom_error.js +++ b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_custom_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapCustomError } from '../wrap_custom_error'; describe('wrap_custom_error', () => { diff --git a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_es_error.js index b8d59590ebf33..f3237563edb45 100644 --- a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_es_error.js +++ b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_es_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapEsError } from '../wrap_es_error'; describe('wrap_es_error', () => { diff --git a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_unknown_error.js index 6d6a336417bef..85e0b2b3033ad 100644 --- a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_unknown_error.js +++ b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_unknown_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapUnknownError } from '../wrap_unknown_error'; describe('wrap_unknown_error', () => { diff --git a/x-pack/plugins/remote_clusters/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/remote_clusters/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js index d50ff9480d3e4..76fdf7b36c3d0 100644 --- a/x-pack/plugins/remote_clusters/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js +++ b/x-pack/plugins/remote_clusters/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isEsErrorFactory } from '../is_es_error_factory'; import { set } from 'lodash'; diff --git a/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index ffbbd1395a418..dc641bef91085 100644 --- a/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { licensePreRoutingFactory } from '../license_pre_routing_factory'; describe('license_pre_routing_factory', () => { diff --git a/x-pack/plugins/reporting/common/__tests__/export_types_registry.js b/x-pack/plugins/reporting/common/__tests__/export_types_registry.js index 9df8b8b47f50f..02aff84fb7d0d 100644 --- a/x-pack/plugins/reporting/common/__tests__/export_types_registry.js +++ b/x-pack/plugins/reporting/common/__tests__/export_types_registry.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ExportTypesRegistry } from '../export_types_registry'; describe('ExportTypesRegistry', function () { diff --git a/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js b/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js index ee851694f03d0..b8799f7a516d9 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js +++ b/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Puid from 'puid'; import sinon from 'sinon'; import nodeCrypto from '@elastic/node-crypto'; diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js index e8dd84637589c..7e2b38f380e8d 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js +++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createEscapeValue } from '../escape_value'; describe('escapeValue', function () { diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js index d11552daf9e89..15d2bbbc60a44 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js +++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { FieldFormat } from '../../../../../../../../src/legacy/ui/field_formats/field_format.js'; import { FieldFormatsService } from '../../../../../../../../src/legacy/ui/field_formats/field_formats_service.js'; diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js index 005862a61fee1..4abf31bb3e5e3 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js +++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createFlattenHit } from '../flatten_hit'; describe('flattenHit', function () { diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js index 9faa32fee9b0b..e3d588b5f48f1 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js +++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { createFormatCsvValues } from '../format_csv_values'; describe('formatCsvValues', function () { diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js index 15a10934b5db5..32b68e6c7ba09 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js +++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { MaxSizeStringBuilder } from '../max_size_string_builder'; describe('MaxSizeStringBuilder', function () { diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/extract.js b/x-pack/plugins/reporting/server/browsers/extract/__tests__/extract.js index cf81cbf5ced28..e3af8b2c0029a 100644 --- a/x-pack/plugins/reporting/server/browsers/extract/__tests__/extract.js +++ b/x-pack/plugins/reporting/server/browsers/extract/__tests__/extract.js @@ -6,7 +6,7 @@ import fs from 'fs'; import crypto from 'crypto'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { resolve } from 'path'; import { extract } from '../extract'; diff --git a/x-pack/plugins/reporting/server/lib/__tests__/check_license.js b/x-pack/plugins/reporting/server/lib/__tests__/check_license.js index dc42258a7897a..480cf4d3e14e2 100644 --- a/x-pack/plugins/reporting/server/lib/__tests__/check_license.js +++ b/x-pack/plugins/reporting/server/lib/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { checkLicenseFactory } from '../check_license'; diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js index 5a394c1ac29f5..b40765810fb63 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { CancellationToken } from '../../helpers/cancellation_token'; diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js index 533ba93735c4f..7b0b5e3e468c2 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { createIndex } from '../../helpers/create_index'; import { ClientMock } from '../fixtures/elasticsearch'; diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/errors.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/errors.js index f0264ce3985e2..d41b29106bb9d 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/errors.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/errors.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { WorkerTimeoutError, UnspecifiedWorkerError } from '../../helpers/errors'; describe('custom errors', function () { diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/index_timestamp.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/index_timestamp.js index cfd25e73640d9..e57e62c229ff1 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/index_timestamp.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/index_timestamp.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import moment from 'moment'; import { constants } from '../../constants'; diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/index.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/index.js index ad2da19579387..3d25b45298535 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/index.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/index.js @@ -5,7 +5,7 @@ */ import events from 'events'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import proxyquire from 'proxyquire'; import { noop, times } from 'lodash'; diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js index 15ef68c1cb834..233ecb07ca44c 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js @@ -5,7 +5,7 @@ */ import events from 'events'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import proxyquire from 'proxyquire'; import { QueueMock } from './fixtures/queue'; diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js index 7607049479f6b..bb3f9495e88f7 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import moment from 'moment'; import { noop, random, get, find, identity } from 'lodash'; diff --git a/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_config.js b/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_config.js index 78c449b7f6c2d..9a74ba63b8e31 100644 --- a/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_config.js +++ b/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_config.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { validateConfig } from '../validate_config'; diff --git a/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_max_content_length.js b/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_max_content_length.js index 604bd75525298..fc825952e34b4 100644 --- a/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_max_content_length.js +++ b/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_max_content_length.js @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { validateMaxContentLength } from '../validate_max_content_length'; diff --git a/x-pack/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js b/x-pack/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js index 3c5d044212d1f..42b2019507fe9 100644 --- a/x-pack/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js +++ b/x-pack/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { authorizedUserPreRoutingFactory } from '../authorized_user_pre_routing'; diff --git a/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js b/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js index 45953b04143b0..90ec30fd05b5c 100644 --- a/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js +++ b/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { areJobsCompatible, mergeJobConfigurations } from '../jobs_compatibility'; import { jobs } from './fixtures'; diff --git a/x-pack/plugins/rollup/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/rollup/server/lib/check_license/__tests__/check_license.js index 19a7b56759269..394c2c4735c0c 100644 --- a/x-pack/plugins/rollup/server/lib/check_license/__tests__/check_license.js +++ b/x-pack/plugins/rollup/server/lib/check_license/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { checkLicense } from '../check_license'; diff --git a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_custom_error.js index 443744ccb0cc8..f9c102be7a1ff 100644 --- a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_custom_error.js +++ b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_custom_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapCustomError } from '../wrap_custom_error'; describe('wrap_custom_error', () => { diff --git a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_es_error.js index b8d59590ebf33..f3237563edb45 100644 --- a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_es_error.js +++ b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_es_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapEsError } from '../wrap_es_error'; describe('wrap_es_error', () => { diff --git a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_unknown_error.js index 6d6a336417bef..85e0b2b3033ad 100644 --- a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_unknown_error.js +++ b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_unknown_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapUnknownError } from '../wrap_unknown_error'; describe('wrap_unknown_error', () => { diff --git a/x-pack/plugins/rollup/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/rollup/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js index d50ff9480d3e4..76fdf7b36c3d0 100644 --- a/x-pack/plugins/rollup/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js +++ b/x-pack/plugins/rollup/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isEsErrorFactory } from '../is_es_error_factory'; import { set } from 'lodash'; diff --git a/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index ffbbd1395a418..dc641bef91085 100644 --- a/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { licensePreRoutingFactory } from '../license_pre_routing_factory'; describe('license_pre_routing_factory', () => { diff --git a/x-pack/plugins/searchprofiler/public/__tests__/app_util.js b/x-pack/plugins/searchprofiler/public/__tests__/app_util.js index 2c085296d0dbb..164e7394dead7 100644 --- a/x-pack/plugins/searchprofiler/public/__tests__/app_util.js +++ b/x-pack/plugins/searchprofiler/public/__tests__/app_util.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { checkForParseErrors } from '../app_util.js'; describe('checkForParseErrors', function () { diff --git a/x-pack/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js b/x-pack/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js index 745cfb94ac811..6da9a452e5e3c 100644 --- a/x-pack/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js +++ b/x-pack/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as util from '../util.js'; import { normalized, breakdown } from './fixtures/breakdown.js'; import { inputTimes, normalizedTimes } from './fixtures/normalize_times.js'; diff --git a/x-pack/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js b/x-pack/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js index 3519c411951f0..85208495fc18e 100644 --- a/x-pack/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js +++ b/x-pack/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { nsToPretty } from '../ns_to_pretty.js'; describe('nsToPretty', function () { diff --git a/x-pack/plugins/searchprofiler/server/lib/__tests__/check_license.js b/x-pack/plugins/searchprofiler/server/lib/__tests__/check_license.js index 17dacc31680be..f1e19b61cbe2b 100644 --- a/x-pack/plugins/searchprofiler/server/lib/__tests__/check_license.js +++ b/x-pack/plugins/searchprofiler/server/lib/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { checkLicense } from '../check_license'; diff --git a/x-pack/plugins/security/public/lib/__tests__/parse_next.js b/x-pack/plugins/security/public/lib/__tests__/parse_next.js index 615c348c33b1c..7516433c77f83 100644 --- a/x-pack/plugins/security/public/lib/__tests__/parse_next.js +++ b/x-pack/plugins/security/public/lib/__tests__/parse_next.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { parseNext } from '../parse_next'; describe('parseNext', () => { diff --git a/x-pack/plugins/security/public/lib/__tests__/util.js b/x-pack/plugins/security/public/lib/__tests__/util.js index 766c384456aa6..3f7d8aea53a85 100644 --- a/x-pack/plugins/security/public/lib/__tests__/util.js +++ b/x-pack/plugins/security/public/lib/__tests__/util.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { toggle, toggleSort } from '../../../public/lib/util'; describe('util', () => { diff --git a/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js b/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js index c511eca58ac4d..32bc341ce58fa 100644 --- a/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js +++ b/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js @@ -5,7 +5,7 @@ */ import Boom from 'boom'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { hFixture } from './__fixtures__/h'; diff --git a/x-pack/plugins/security/server/lib/__tests__/auth_scope_service.js b/x-pack/plugins/security/server/lib/__tests__/auth_scope_service.js index 8f3c3acede0be..d54d53d12142b 100644 --- a/x-pack/plugins/security/server/lib/__tests__/auth_scope_service.js +++ b/x-pack/plugins/security/server/lib/__tests__/auth_scope_service.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { AuthScopeService } from '../auth_scope_service'; diff --git a/x-pack/plugins/security/server/lib/__tests__/check_license.js b/x-pack/plugins/security/server/lib/__tests__/check_license.js index 365cf399519d9..a2bf1faf031e3 100644 --- a/x-pack/plugins/security/server/lib/__tests__/check_license.js +++ b/x-pack/plugins/security/server/lib/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { checkLicense } from '../check_license'; diff --git a/x-pack/plugins/security/server/lib/__tests__/errors.js b/x-pack/plugins/security/server/lib/__tests__/errors.js index 5ec42f7d30f0c..2cf7b6957a2ba 100644 --- a/x-pack/plugins/security/server/lib/__tests__/errors.js +++ b/x-pack/plugins/security/server/lib/__tests__/errors.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as errors from '../errors'; diff --git a/x-pack/plugins/security/server/lib/__tests__/parse_next.js b/x-pack/plugins/security/server/lib/__tests__/parse_next.js index 615c348c33b1c..7516433c77f83 100644 --- a/x-pack/plugins/security/server/lib/__tests__/parse_next.js +++ b/x-pack/plugins/security/server/lib/__tests__/parse_next.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { parseNext } from '../parse_next'; describe('parseNext', () => { diff --git a/x-pack/plugins/security/server/lib/__tests__/validate_config.js b/x-pack/plugins/security/server/lib/__tests__/validate_config.js index 26d84f6f5559b..c5a96bc8253f1 100644 --- a/x-pack/plugins/security/server/lib/__tests__/validate_config.js +++ b/x-pack/plugins/security/server/lib/__tests__/validate_config.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { validateConfig } from '../validate_config'; diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js index de5061fc65ba2..44916c6a7bb82 100644 --- a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js +++ b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import Boom from 'boom'; diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/session.js b/x-pack/plugins/security/server/lib/authentication/__tests__/session.js index 832adef2439ee..4a47fe12c68bf 100644 --- a/x-pack/plugins/security/server/lib/authentication/__tests__/session.js +++ b/x-pack/plugins/security/server/lib/authentication/__tests__/session.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { serverFixture } from '../../__tests__/__fixtures__/server'; diff --git a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js index 0226c9b36b5c9..eaaa6fae4df3c 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js +++ b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { requestFixture } from '../../../__tests__/__fixtures__/request'; import { LoginAttempt } from '../../login_attempt'; diff --git a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js index 902db0fc1a2dc..ebc33d6b7f596 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js +++ b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { requestFixture } from '../../../__tests__/__fixtures__/request'; import { LoginAttempt } from '../../login_attempt'; diff --git a/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js b/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js index 0945782e932b5..df87a630a98c0 100644 --- a/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js +++ b/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Boom from 'boom'; import Joi from 'joi'; import sinon from 'sinon'; diff --git a/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js b/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js index 39ab7d7627bdb..05c5cad41e2c3 100644 --- a/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js +++ b/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import Joi from 'joi'; import sinon from 'sinon'; diff --git a/x-pack/plugins/tilemap/server/lib/__tests__/inspect_settings.js b/x-pack/plugins/tilemap/server/lib/__tests__/inspect_settings.js index a50a9298e2ee7..3f900c3b6af67 100644 --- a/x-pack/plugins/tilemap/server/lib/__tests__/inspect_settings.js +++ b/x-pack/plugins/tilemap/server/lib/__tests__/inspect_settings.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { inspectSettings } from '../../../server/lib/inspect_settings'; describe('inspectSettings', function () { diff --git a/x-pack/plugins/watcher/__tests__/plugin_definition.js b/x-pack/plugins/watcher/__tests__/plugin_definition.js index eb0c2d011eb6a..c95d5aba8bbc5 100644 --- a/x-pack/plugins/watcher/__tests__/plugin_definition.js +++ b/x-pack/plugins/watcher/__tests__/plugin_definition.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { pluginDefinition } from '../plugin_definition'; describe ('pluginDefinition', () => { diff --git a/x-pack/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js b/x-pack/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js index 3ee5a1d75b4b4..7b2fd7bd84062 100644 --- a/x-pack/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js +++ b/x-pack/plugins/watcher/common/lib/get_action_type/__tests__/get_action_type.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getActionType } from '../get_action_type'; import { ACTION_TYPES } from '../../../../common/constants'; diff --git a/x-pack/plugins/watcher/common/lib/get_moment/__tests__/get_moment.js b/x-pack/plugins/watcher/common/lib/get_moment/__tests__/get_moment.js index 69ccd634ec6e7..a90099f465ccd 100644 --- a/x-pack/plugins/watcher/common/lib/get_moment/__tests__/get_moment.js +++ b/x-pack/plugins/watcher/common/lib/get_moment/__tests__/get_moment.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getMoment } from '../get_moment'; describe('get_moment', () => { diff --git a/x-pack/plugins/watcher/public/lib/sortable_boolean/__tests__/sortable_boolean.js b/x-pack/plugins/watcher/public/lib/sortable_boolean/__tests__/sortable_boolean.js index ba32ba27f53d1..b51130c836459 100644 --- a/x-pack/plugins/watcher/public/lib/sortable_boolean/__tests__/sortable_boolean.js +++ b/x-pack/plugins/watcher/public/lib/sortable_boolean/__tests__/sortable_boolean.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { sortableBoolean } from '../sortable_boolean'; describe('sortable_boolean', () => { diff --git a/x-pack/plugins/watcher/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/watcher/server/lib/check_license/__tests__/check_license.js index fe410e498b91a..3dc2eced25a8e 100644 --- a/x-pack/plugins/watcher/server/lib/check_license/__tests__/check_license.js +++ b/x-pack/plugins/watcher/server/lib/check_license/__tests__/check_license.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { checkLicense } from '../check_license'; diff --git a/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_custom_error.js index 443744ccb0cc8..f9c102be7a1ff 100644 --- a/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_custom_error.js +++ b/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_custom_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapCustomError } from '../wrap_custom_error'; describe('wrap_custom_error', () => { diff --git a/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_es_error.js index 394c182140000..467cc4fcdae1f 100644 --- a/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_es_error.js +++ b/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_es_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapEsError } from '../wrap_es_error'; describe('wrap_es_error', () => { diff --git a/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_unknown_error.js index 6d6a336417bef..85e0b2b3033ad 100644 --- a/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_unknown_error.js +++ b/x-pack/plugins/watcher/server/lib/error_wrappers/__tests__/wrap_unknown_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapUnknownError } from '../wrap_unknown_error'; describe('wrap_unknown_error', () => { diff --git a/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js index 582c021892d42..5e532b68e2bcc 100644 --- a/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js +++ b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { fetchAllFromScroll } from '../fetch_all_from_scroll'; import { set } from 'lodash'; diff --git a/x-pack/plugins/watcher/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/watcher/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js index d50ff9480d3e4..76fdf7b36c3d0 100644 --- a/x-pack/plugins/watcher/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js +++ b/x-pack/plugins/watcher/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isEsErrorFactory } from '../is_es_error_factory'; import { set } from 'lodash'; diff --git a/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index 359b3fb2ce6f4..24cbaae2b2b67 100644 --- a/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { licensePreRoutingFactory } from '../license_pre_routing_factory'; describe('license_pre_routing_factory', () => { diff --git a/x-pack/plugins/watcher/server/models/action_status/__tests__/action_status.js b/x-pack/plugins/watcher/server/models/action_status/__tests__/action_status.js index b30d29af611d7..911c960efdab5 100644 --- a/x-pack/plugins/watcher/server/models/action_status/__tests__/action_status.js +++ b/x-pack/plugins/watcher/server/models/action_status/__tests__/action_status.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ActionStatus } from '../action_status'; import { ACTION_STATES } from '../../../../common/constants'; import moment from 'moment'; diff --git a/x-pack/plugins/watcher/server/models/execute_details/__tests__/execute_details.js b/x-pack/plugins/watcher/server/models/execute_details/__tests__/execute_details.js index bdd4a13eb8e37..00937bbc6204c 100644 --- a/x-pack/plugins/watcher/server/models/execute_details/__tests__/execute_details.js +++ b/x-pack/plugins/watcher/server/models/execute_details/__tests__/execute_details.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ExecuteDetails } from '../execute_details'; describe('execute_details', () => { diff --git a/x-pack/plugins/watcher/server/models/fields/__tests__/fields.js b/x-pack/plugins/watcher/server/models/fields/__tests__/fields.js index 9588c51a2ad4f..5c872ff56749c 100644 --- a/x-pack/plugins/watcher/server/models/fields/__tests__/fields.js +++ b/x-pack/plugins/watcher/server/models/fields/__tests__/fields.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { find } from 'lodash'; import { Fields } from '../fields'; diff --git a/x-pack/plugins/watcher/server/models/settings/__tests__/settings.js b/x-pack/plugins/watcher/server/models/settings/__tests__/settings.js index 6c34467ef8629..7add7a0e0564e 100644 --- a/x-pack/plugins/watcher/server/models/settings/__tests__/settings.js +++ b/x-pack/plugins/watcher/server/models/settings/__tests__/settings.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { Settings } from '../settings'; describe('settings module', () => { diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/base_watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/base_watch.js index 9740874cb92ac..fbbbd52c7987b 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/base_watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/base_watch.js @@ -5,7 +5,7 @@ */ import proxyquire from 'proxyquire'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; const actionFromUpstreamJSONMock = sinon.stub(); diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/json_watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/json_watch.js index e4b258d51cfe5..a38b10afcd28f 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/json_watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/json_watch.js @@ -5,7 +5,7 @@ */ import { pick } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import proxyquire from 'proxyquire'; diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/monitoring_watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/monitoring_watch.js index c580d8c8f7768..44e457476815d 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/monitoring_watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/monitoring_watch.js @@ -5,7 +5,7 @@ */ import { pick } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import proxyquire from 'proxyquire'; diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/threshold_watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/threshold_watch.js index 635d23734b968..a93280d5c6aa8 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/threshold_watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/threshold_watch.js @@ -5,7 +5,7 @@ */ import { pick } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import proxyquire from 'proxyquire'; import { COMPARATORS, SORT_ORDERS } from '../../../../common/constants'; diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/watch.js index ac186b3846579..14d5005b13e04 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/watch.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import proxyquire from 'proxyquire'; import { WATCH_TYPES } from '../../../../common/constants'; diff --git a/x-pack/plugins/watcher/server/models/watch/threshold_watch/__tests__/format_visualize_data.js b/x-pack/plugins/watcher/server/models/watch/threshold_watch/__tests__/format_visualize_data.js index 41c84f1750a5e..04239ab6e1b5f 100644 --- a/x-pack/plugins/watcher/server/models/watch/threshold_watch/__tests__/format_visualize_data.js +++ b/x-pack/plugins/watcher/server/models/watch/threshold_watch/__tests__/format_visualize_data.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { AGG_TYPES } from '../../../../../common/constants'; import { formatVisualizeData } from '../format_visualize_data'; diff --git a/x-pack/plugins/watcher/server/models/watch_history_item/__tests__/watch_history_item.js b/x-pack/plugins/watcher/server/models/watch_history_item/__tests__/watch_history_item.js index 2d13243f8a6d3..a22609db226e5 100644 --- a/x-pack/plugins/watcher/server/models/watch_history_item/__tests__/watch_history_item.js +++ b/x-pack/plugins/watcher/server/models/watch_history_item/__tests__/watch_history_item.js @@ -5,7 +5,7 @@ */ import moment from 'moment'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { WatchHistoryItem } from '../watch_history_item'; describe('watch_history_item', () => { diff --git a/x-pack/plugins/watcher/server/models/watch_status/__tests__/watch_status.js b/x-pack/plugins/watcher/server/models/watch_status/__tests__/watch_status.js index 4b1649ab4c1e0..e29c8dd2a529e 100644 --- a/x-pack/plugins/watcher/server/models/watch_status/__tests__/watch_status.js +++ b/x-pack/plugins/watcher/server/models/watch_status/__tests__/watch_status.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { WatchStatus } from '../watch_status'; import { ACTION_STATES, WATCH_STATES, WATCH_STATE_COMMENTS } from '../../../../common/constants'; import moment from 'moment'; diff --git a/x-pack/plugins/xpack_main/public/hacks/__tests__/fetch_telemetry.js b/x-pack/plugins/xpack_main/public/hacks/__tests__/fetch_telemetry.js index 903abf4d202db..1dfeefdd295ec 100644 --- a/x-pack/plugins/xpack_main/public/hacks/__tests__/fetch_telemetry.js +++ b/x-pack/plugins/xpack_main/public/hacks/__tests__/fetch_telemetry.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { fetchTelemetry } from '../fetch_telemetry'; diff --git a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/click_banner.js b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/click_banner.js index 3a1e528e3fc41..d77c77cf53356 100644 --- a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/click_banner.js +++ b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/click_banner.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { uiModules } from 'ui/modules'; diff --git a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/handle_old_settings.js b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/handle_old_settings.js index 3ceb31cb2eb30..ab17b0080463d 100644 --- a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/handle_old_settings.js +++ b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/handle_old_settings.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { CONFIG_TELEMETRY } from '../../../../common/constants'; diff --git a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/render_banner.js b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/render_banner.js index de8c690c1a391..0ba0a21b6413b 100644 --- a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/render_banner.js +++ b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/render_banner.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { renderBanner } from '../render_banner'; diff --git a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/should_show_banner.js b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/should_show_banner.js index ed9d3e79a0c59..e78d69f25ecb3 100644 --- a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/should_show_banner.js +++ b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/__tests__/should_show_banner.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { CONFIG_TELEMETRY } from '../../../../common/constants'; diff --git a/x-pack/plugins/xpack_main/public/services/__tests__/xpack_info.js b/x-pack/plugins/xpack_main/public/services/__tests__/xpack_info.js index 70eb4925fe1a7..a6ee8cb0c8d6a 100644 --- a/x-pack/plugins/xpack_main/public/services/__tests__/xpack_info.js +++ b/x-pack/plugins/xpack_main/public/services/__tests__/xpack_info.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info'; import { MockWindowProvider } from './_mock_window'; diff --git a/x-pack/plugins/xpack_main/public/services/__tests__/xpack_info_signature.js b/x-pack/plugins/xpack_main/public/services/__tests__/xpack_info_signature.js index 47db141d610d4..980d8f649f1d4 100644 --- a/x-pack/plugins/xpack_main/public/services/__tests__/xpack_info_signature.js +++ b/x-pack/plugins/xpack_main/public/services/__tests__/xpack_info_signature.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import { XPackInfoSignatureProvider } from 'plugins/xpack_main/services/xpack_info_signature'; import { MockWindowProvider } from './_mock_window'; diff --git a/x-pack/plugins/xpack_main/server/lib/__tests__/call_cluster_factory.js b/x-pack/plugins/xpack_main/server/lib/__tests__/call_cluster_factory.js index 9c7f17a9e507b..9251829f07608 100644 --- a/x-pack/plugins/xpack_main/server/lib/__tests__/call_cluster_factory.js +++ b/x-pack/plugins/xpack_main/server/lib/__tests__/call_cluster_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { callClusterFactory } from '../call_cluster_factory'; diff --git a/x-pack/plugins/xpack_main/server/lib/__tests__/inject_xpack_info_signature.js b/x-pack/plugins/xpack_main/server/lib/__tests__/inject_xpack_info_signature.js index c044636a2c93a..c0f52b1cb7f1f 100644 --- a/x-pack/plugins/xpack_main/server/lib/__tests__/inject_xpack_info_signature.js +++ b/x-pack/plugins/xpack_main/server/lib/__tests__/inject_xpack_info_signature.js @@ -5,7 +5,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { injectXPackInfoSignature } from '../inject_xpack_info_signature'; describe('injectXPackInfoSignature()', () => { diff --git a/x-pack/plugins/xpack_main/server/lib/__tests__/replace_injected_vars.js b/x-pack/plugins/xpack_main/server/lib/__tests__/replace_injected_vars.js index 863f07725ad29..26bce06adaaba 100644 --- a/x-pack/plugins/xpack_main/server/lib/__tests__/replace_injected_vars.js +++ b/x-pack/plugins/xpack_main/server/lib/__tests__/replace_injected_vars.js @@ -5,7 +5,7 @@ */ import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { replaceInjectedVars } from '../replace_injected_vars'; diff --git a/x-pack/plugins/xpack_main/server/lib/__tests__/xpack_info.js b/x-pack/plugins/xpack_main/server/lib/__tests__/xpack_info.js index 8cb75f3cb642b..88ba3d6003277 100644 --- a/x-pack/plugins/xpack_main/server/lib/__tests__/xpack_info.js +++ b/x-pack/plugins/xpack_main/server/lib/__tests__/xpack_info.js @@ -5,7 +5,7 @@ */ import { createHash } from 'crypto'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { XPackInfo } from '../xpack_info'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_cluster_info.js b/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_cluster_info.js index 2331c8b01bce8..863556b70df45 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_cluster_info.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_cluster_info.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { getClusterInfo } from '../get_cluster_info'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_cluster_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_cluster_stats.js index 6e3bc59928a21..ce4620d34601a 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_cluster_stats.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_cluster_stats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { TIMEOUT } from '../constants'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_local_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_local_stats.js index 03056f8c9e26b..153166c4b1f1e 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_local_stats.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_local_stats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { mockGetClusterInfo } from './get_cluster_info'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_xpack.js b/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_xpack.js index c4cc1fa249a17..bc9c6981e4410 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_xpack.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/local/__tests__/get_xpack.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { TIMEOUT } from '../constants'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/create_query.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/create_query.js index 7ad932bdef024..2d35c10ea2189 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/create_query.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/create_query.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { set } from 'lodash'; import { createTypeFilter, createQuery } from '../create_query.js'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_all_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_all_stats.js index 3357f27ad6447..fff281a0d87ef 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_all_stats.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_all_stats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { addStackStats, getAllStats, getAllStatsForServer, handleAllStats } from '../get_all_stats'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_beats_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_beats_stats.js index 42642b16de4c4..529cd306275b1 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_beats_stats.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_beats_stats.js @@ -6,7 +6,7 @@ import { fetchBeatsStats, processResults } from '../get_beats_stats'; import sinon from 'sinon'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import beatsStatsResultSet from './fixtures/beats_stats_results'; const getBaseOptions = () => ({ diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_cluster_uuids.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_cluster_uuids.js index 6ec260f8f4f4c..e3153670ac58f 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_cluster_uuids.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_cluster_uuids.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { getClusterUuids, fetchClusterUuids, handleClusterUuidsResponse } from '../get_cluster_uuids'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_es_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_es_stats.js index 5005037bd641b..6f13a1e1bdf75 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_es_stats.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_es_stats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { fetchElasticsearchStats, getElasticsearchStats, handleElasticsearchStats } from '../get_es_stats'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_high_level_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_high_level_stats.js index a071837a163f2..be86130f2452e 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_high_level_stats.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_high_level_stats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { fetchHighLevelStats, getHighLevelStats, handleHighLevelStatsResponse } from '../get_high_level_stats'; diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_kibana_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_kibana_stats.js index 4811f825ed7bb..4d0ad95c919c8 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_kibana_stats.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_kibana_stats.js @@ -5,7 +5,7 @@ */ import { getUsageStats, combineStats, rollUpTotals } from '../get_kibana_stats'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; describe('Get Kibana Stats', () => { describe('Make a map of usage stats for each cluster', () => { diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js b/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js index 9e095a12dad78..178564e4578fb 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { xpackInfoRoute } from '../xpack_info'; diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/telemetry/__tests__/telemetry.js b/x-pack/plugins/xpack_main/server/routes/api/v1/telemetry/__tests__/telemetry.js index a16d9187e2ca4..1d657df734fe6 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/telemetry/__tests__/telemetry.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/telemetry/__tests__/telemetry.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import sinon from 'sinon'; import { getTelemetry } from '../telemetry'; diff --git a/x-pack/server/lib/__tests__/key_case_converter.js b/x-pack/server/lib/__tests__/key_case_converter.js index 78a627ffc8553..b5f4515844d15 100644 --- a/x-pack/server/lib/__tests__/key_case_converter.js +++ b/x-pack/server/lib/__tests__/key_case_converter.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { convertKeysToSnakeCaseDeep, convertKeysToCamelCaseDeep } from '../key_case_converter'; describe('key_case_converter', () => { diff --git a/x-pack/server/lib/__tests__/kibana_state.js b/x-pack/server/lib/__tests__/kibana_state.js index 3b0b8f8a2ea2d..f0576701c980a 100644 --- a/x-pack/server/lib/__tests__/kibana_state.js +++ b/x-pack/server/lib/__tests__/kibana_state.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import rison from 'rison-node'; import { parseKibanaState } from '../parse_kibana_state'; diff --git a/x-pack/server/lib/__tests__/mirror_plugin_status.js b/x-pack/server/lib/__tests__/mirror_plugin_status.js index 4383932141543..745c69b7a3d70 100644 --- a/x-pack/server/lib/__tests__/mirror_plugin_status.js +++ b/x-pack/server/lib/__tests__/mirror_plugin_status.js @@ -5,7 +5,7 @@ */ import EventEmitter from 'events'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { mirrorPluginStatus } from '../mirror_plugin_status'; describe('mirror_plugin_status', () => { diff --git a/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_custom_error.js index 443744ccb0cc8..f9c102be7a1ff 100644 --- a/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_custom_error.js +++ b/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_custom_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapCustomError } from '../wrap_custom_error'; describe('wrap_custom_error', () => { diff --git a/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_es_error.js b/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_es_error.js index 394c182140000..467cc4fcdae1f 100644 --- a/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_es_error.js +++ b/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_es_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapEsError } from '../wrap_es_error'; describe('wrap_es_error', () => { diff --git a/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_unknown_error.js index 6d6a336417bef..85e0b2b3033ad 100644 --- a/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_unknown_error.js +++ b/x-pack/server/lib/create_router/error_wrappers/__tests__/wrap_unknown_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { wrapUnknownError } from '../wrap_unknown_error'; describe('wrap_unknown_error', () => { diff --git a/x-pack/server/lib/create_router/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/server/lib/create_router/is_es_error_factory/__tests__/is_es_error_factory.js index d50ff9480d3e4..76fdf7b36c3d0 100644 --- a/x-pack/server/lib/create_router/is_es_error_factory/__tests__/is_es_error_factory.js +++ b/x-pack/server/lib/create_router/is_es_error_factory/__tests__/is_es_error_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { isEsErrorFactory } from '../is_es_error_factory'; import { set } from 'lodash'; diff --git a/x-pack/server/lib/create_router/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/server/lib/create_router/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index 5192181d37767..cbb0ca1d6076a 100644 --- a/x-pack/server/lib/create_router/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/server/lib/create_router/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { licensePreRoutingFactory } from '../license_pre_routing_factory'; import { LICENSE_STATUS_INVALID, LICENSE_STATUS_VALID } from '../../../../../common/constants'; diff --git a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js index a1268eea645eb..2fa316b4d6476 100644 --- a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js +++ b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js b/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js index ba3d6792367ee..246fc13812a06 100644 --- a/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js +++ b/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { ES_INDEX_NAME } from './constants'; diff --git a/x-pack/test/api_integration/apis/beats/enroll_beat.js b/x-pack/test/api_integration/apis/beats/enroll_beat.js index 72933f2950225..395886fc550a6 100644 --- a/x-pack/test/api_integration/apis/beats/enroll_beat.js +++ b/x-pack/test/api_integration/apis/beats/enroll_beat.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import moment from 'moment'; import { ES_INDEX_NAME } from './constants'; diff --git a/x-pack/test/api_integration/apis/beats/get_beat.js b/x-pack/test/api_integration/apis/beats/get_beat.js index bb300f5c3e230..7d5979fc65ac0 100644 --- a/x-pack/test/api_integration/apis/beats/get_beat.js +++ b/x-pack/test/api_integration/apis/beats/get_beat.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/beats/list_beats.js b/x-pack/test/api_integration/apis/beats/list_beats.js index b78939b30b62f..456ecc318b166 100644 --- a/x-pack/test/api_integration/apis/beats/list_beats.js +++ b/x-pack/test/api_integration/apis/beats/list_beats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js b/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js index 1bc0664d6f80e..fc55ee9d9da29 100644 --- a/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js +++ b/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/beats/set_config.js b/x-pack/test/api_integration/apis/beats/set_config.js index 2c023ecbbf0ae..53fa2b0133ee4 100644 --- a/x-pack/test/api_integration/apis/beats/set_config.js +++ b/x-pack/test/api_integration/apis/beats/set_config.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/beats/set_tag.js b/x-pack/test/api_integration/apis/beats/set_tag.js index 445f939dd80cd..ee9a601b25096 100644 --- a/x-pack/test/api_integration/apis/beats/set_tag.js +++ b/x-pack/test/api_integration/apis/beats/set_tag.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ES_INDEX_NAME } from './constants'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/beats/update_beat.js b/x-pack/test/api_integration/apis/beats/update_beat.js index ba8ed8b9631f8..e700414d45b05 100644 --- a/x-pack/test/api_integration/apis/beats/update_beat.js +++ b/x-pack/test/api_integration/apis/beats/update_beat.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ES_INDEX_NAME } from './constants'; import moment from 'moment'; diff --git a/x-pack/test/api_integration/apis/es/has_privileges.js b/x-pack/test/api_integration/apis/es/has_privileges.js index 21283d483ca37..5cbbefd8f2f37 100644 --- a/x-pack/test/api_integration/apis/es/has_privileges.js +++ b/x-pack/test/api_integration/apis/es/has_privileges.js @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; const application = 'has_privileges_test'; diff --git a/x-pack/test/api_integration/apis/es/post_privileges.js b/x-pack/test/api_integration/apis/es/post_privileges.js index bf2266575d3b1..4b1695487f832 100644 --- a/x-pack/test/api_integration/apis/es/post_privileges.js +++ b/x-pack/test/api_integration/apis/es/post_privileges.js @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/infra/log_entries.ts b/x-pack/test/api_integration/apis/infra/log_entries.ts index c2e37e5e578d5..79a39163e235d 100644 --- a/x-pack/test/api_integration/apis/infra/log_entries.ts +++ b/x-pack/test/api_integration/apis/infra/log_entries.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import expect from '@kbn/expect'; import { ascending, pairs } from 'd3-array'; -import expect from 'expect.js'; import gql from 'graphql-tag'; import { InfraTimeKey } from '../../../../plugins/infra/public/graphql/types'; diff --git a/x-pack/test/api_integration/apis/infra/log_item.ts b/x-pack/test/api_integration/apis/infra/log_item.ts index bfdde32fa57ae..798f12477a811 100644 --- a/x-pack/test/api_integration/apis/infra/log_item.ts +++ b/x-pack/test/api_integration/apis/infra/log_item.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { flyoutItemQuery } from '../../../../plugins/infra/public/containers/logs/flyout_item.gql_query'; import { FlyoutItemQuery } from '../../../../plugins/infra/public/graphql/types'; import { KbnTestProvider } from './types'; diff --git a/x-pack/test/api_integration/apis/infra/log_summary.ts b/x-pack/test/api_integration/apis/infra/log_summary.ts index 7530ec3030794..2682987f9c0ba 100644 --- a/x-pack/test/api_integration/apis/infra/log_summary.ts +++ b/x-pack/test/api_integration/apis/infra/log_summary.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import expect from '@kbn/expect'; import { pairs } from 'd3-array'; -import expect from 'expect.js'; import gql from 'graphql-tag'; import { KbnTestProvider } from './types'; diff --git a/x-pack/test/api_integration/apis/infra/logs_without_millis.ts b/x-pack/test/api_integration/apis/infra/logs_without_millis.ts index 94301c7f42789..5e67b82508e92 100644 --- a/x-pack/test/api_integration/apis/infra/logs_without_millis.ts +++ b/x-pack/test/api_integration/apis/infra/logs_without_millis.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import expect from '@kbn/expect'; import { ascending, pairs } from 'd3-array'; -import expect from 'expect.js'; import gql from 'graphql-tag'; import { InfraTimeKey } from '../../../../plugins/infra/public/graphql/types'; diff --git a/x-pack/test/api_integration/apis/infra/metadata.ts b/x-pack/test/api_integration/apis/infra/metadata.ts index 749c31fe2b7a3..76cc2da7b7ad3 100644 --- a/x-pack/test/api_integration/apis/infra/metadata.ts +++ b/x-pack/test/api_integration/apis/infra/metadata.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { metadataQuery } from '../../../../plugins/infra/public/containers/metadata/metadata.gql_query'; import { MetadataQuery } from '../../../../plugins/infra/public/graphql/types'; diff --git a/x-pack/test/api_integration/apis/infra/metrics.ts b/x-pack/test/api_integration/apis/infra/metrics.ts index 52d593789e8e2..6cf3723063d5b 100644 --- a/x-pack/test/api_integration/apis/infra/metrics.ts +++ b/x-pack/test/api_integration/apis/infra/metrics.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { first, last } from 'lodash'; import { metricsQuery } from '../../../../plugins/infra/public/containers/metrics/metrics.gql_query'; diff --git a/x-pack/test/api_integration/apis/infra/sources.ts b/x-pack/test/api_integration/apis/infra/sources.ts index d0002e73d9875..952c1a0dd3baa 100644 --- a/x-pack/test/api_integration/apis/infra/sources.ts +++ b/x-pack/test/api_integration/apis/infra/sources.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import gql from 'graphql-tag'; import { sourceQuery } from '../../../../plugins/infra/public/containers/with_source/query_source.gql_query'; diff --git a/x-pack/test/api_integration/apis/infra/waffle.ts b/x-pack/test/api_integration/apis/infra/waffle.ts index 023bdd4f7bc7a..f7aafc1352029 100644 --- a/x-pack/test/api_integration/apis/infra/waffle.ts +++ b/x-pack/test/api_integration/apis/infra/waffle.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { first, last } from 'lodash'; import { waffleNodesQuery } from '../../../../plugins/infra/public/containers/waffle/waffle_nodes.gql_query'; diff --git a/x-pack/test/api_integration/apis/kibana/kql_telemetry/kql_telemetry.js b/x-pack/test/api_integration/apis/kibana/kql_telemetry/kql_telemetry.js index ab47576cdc239..43f00b920420d 100644 --- a/x-pack/test/api_integration/apis/kibana/kql_telemetry/kql_telemetry.js +++ b/x-pack/test/api_integration/apis/kibana/kql_telemetry/kql_telemetry.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertestNoAuth = getService('supertestWithoutAuth'); diff --git a/x-pack/test/api_integration/apis/kibana/stats/stats.js b/x-pack/test/api_integration/apis/kibana/stats/stats.js index 8672f64cdf2bd..48c720bb57ba9 100644 --- a/x-pack/test/api_integration/apis/kibana/stats/stats.js +++ b/x-pack/test/api_integration/apis/kibana/stats/stats.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertestNoAuth = getService('supertestWithoutAuth'); diff --git a/x-pack/test/api_integration/apis/logstash/cluster/load.js b/x-pack/test/api_integration/apis/logstash/cluster/load.js index 40ff7adcff987..a20c524f0a8f8 100644 --- a/x-pack/test/api_integration/apis/logstash/cluster/load.js +++ b/x-pack/test/api_integration/apis/logstash/cluster/load.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/load.js b/x-pack/test/api_integration/apis/logstash/pipeline/load.js index 8e5c74154d12c..c7b27348a0a11 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/load.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/load.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import pipeline from './fixtures/load'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/save.js b/x-pack/test/api_integration/apis/logstash/pipeline/save.js index cfcbdf4633d45..73e710c8f9067 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/save.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/save.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/logstash/pipelines/list.js b/x-pack/test/api_integration/apis/logstash/pipelines/list.js index 5c97f5fc933f1..54b2ed0a2b26a 100644 --- a/x-pack/test/api_integration/apis/logstash/pipelines/list.js +++ b/x-pack/test/api_integration/apis/logstash/pipelines/list.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import pipelineList from './fixtures/list'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/management/cross_cluster_replication/auto_follow_pattern.js b/x-pack/test/api_integration/apis/management/cross_cluster_replication/auto_follow_pattern.js index 8274b3b003ff1..82422e13cd19d 100644 --- a/x-pack/test/api_integration/apis/management/cross_cluster_replication/auto_follow_pattern.js +++ b/x-pack/test/api_integration/apis/management/cross_cluster_replication/auto_follow_pattern.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { API_BASE_PATH } from './constants'; diff --git a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js index aa5269d80f593..f93ab9f4629c3 100644 --- a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js +++ b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { FOLLOWER_INDEX_ADVANCED_SETTINGS } from '../../../../../plugins/cross_cluster_replication/common/constants'; import { API_BASE_PATH } from './constants'; diff --git a/x-pack/test/api_integration/apis/management/remote_clusters/remote_clusters.js b/x-pack/test/api_integration/apis/management/remote_clusters/remote_clusters.js index 45ded44276661..6e4946c465cb0 100644 --- a/x-pack/test/api_integration/apis/management/remote_clusters/remote_clusters.js +++ b/x-pack/test/api_integration/apis/management/remote_clusters/remote_clusters.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { API_BASE_PATH, NODE_SEED } from './constants'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js index 0237a5821380c..25bc503682bc7 100644 --- a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js +++ b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import querystring from 'querystring'; import { registerHelpers } from './rollup.test_helpers'; diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup.js b/x-pack/test/api_integration/apis/management/rollup/rollup.js index f00ea63a60db8..64f958e95dd57 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { API_BASE_PATH, ROLLUP_INDEX_NAME } from './constants'; import { registerHelpers } from './rollup.test_helpers'; diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup_search.js b/x-pack/test/api_integration/apis/management/rollup/rollup_search.js index 4455ae8db925e..2a38cd563f312 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup_search.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup_search.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { registerHelpers } from './rollup.test_helpers'; import { API_BASE_PATH } from './constants'; diff --git a/x-pack/test/api_integration/apis/maps/migrations.js b/x-pack/test/api_integration/apis/maps/migrations.js index 74fdc46c80b09..0c1193660a1d1 100644 --- a/x-pack/test/api_integration/apis/maps/migrations.js +++ b/x-pack/test/api_integration/apis/maps/migrations.js @@ -5,7 +5,7 @@ */ /* eslint max-len: 0 */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/monitoring/apm/instance.js b/x-pack/test/api_integration/apis/monitoring/apm/instance.js index f66c64f1fc8e2..b01bf6fdbd066 100644 --- a/x-pack/test/api_integration/apis/monitoring/apm/instance.js +++ b/x-pack/test/api_integration/apis/monitoring/apm/instance.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import apmInstanceFixture from './fixtures/instance'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/apm/instances.js b/x-pack/test/api_integration/apis/monitoring/apm/instances.js index 4ad9a666ab5d1..46abe97c1ea06 100644 --- a/x-pack/test/api_integration/apis/monitoring/apm/instances.js +++ b/x-pack/test/api_integration/apis/monitoring/apm/instances.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/monitoring/apm/overview.js b/x-pack/test/api_integration/apis/monitoring/apm/overview.js index 30a5ae8198b2f..bcdb773837051 100644 --- a/x-pack/test/api_integration/apis/monitoring/apm/overview.js +++ b/x-pack/test/api_integration/apis/monitoring/apm/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import apmClusterFixture from './fixtures/cluster'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/beats/detail.js b/x-pack/test/api_integration/apis/monitoring/beats/detail.js index 1af5277b653af..076b1083d9fad 100644 --- a/x-pack/test/api_integration/apis/monitoring/beats/detail.js +++ b/x-pack/test/api_integration/apis/monitoring/beats/detail.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import beatDetailFixture from './fixtures/detail'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/beats/list.js b/x-pack/test/api_integration/apis/monitoring/beats/list.js index 0ec1ae3226c06..b47703cc6ab3d 100644 --- a/x-pack/test/api_integration/apis/monitoring/beats/list.js +++ b/x-pack/test/api_integration/apis/monitoring/beats/list.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/monitoring/beats/overview.js b/x-pack/test/api_integration/apis/monitoring/beats/overview.js index 67978e948c0af..f1634fcfd7294 100644 --- a/x-pack/test/api_integration/apis/monitoring/beats/overview.js +++ b/x-pack/test/api_integration/apis/monitoring/beats/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import beatsClusterFixture from './fixtures/cluster'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/cluster/list.js b/x-pack/test/api_integration/apis/monitoring/cluster/list.js index 2b920e4f2567c..cc130a340dd6a 100644 --- a/x-pack/test/api_integration/apis/monitoring/cluster/list.js +++ b/x-pack/test/api_integration/apis/monitoring/cluster/list.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import multiclusterFixture from './fixtures/multicluster'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/cluster/overview.js b/x-pack/test/api_integration/apis/monitoring/cluster/overview.js index 57be7082d6971..7b9f5087e78c1 100644 --- a/x-pack/test/api_integration/apis/monitoring/cluster/overview.js +++ b/x-pack/test/api_integration/apis/monitoring/cluster/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import overviewFixture from './fixtures/overview'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js b/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js index a0f1e3bdb4af3..5dd647b97ac43 100644 --- a/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js +++ b/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { get } from 'lodash'; import * as esMetrics from '../../../../../plugins/monitoring/server/lib/metrics/elasticsearch/metrics'; import * as kibanaMetrics from '../../../../../plugins/monitoring/server/lib/metrics/kibana/metrics'; diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/ccr.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/ccr.js index 249baa8c27915..8413217cbb781 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/ccr.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/ccr.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ccrFixture from './fixtures/ccr'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/ccr_shard.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/ccr_shard.js index e5a2418f215b9..776bee5a3eaf0 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/ccr_shard.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/ccr_shard.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import ccrShardFixture from './fixtures/ccr_shard'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/index_detail.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/index_detail.js index b9af7be8154aa..de21b697a7dc5 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/index_detail.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/index_detail.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import indexDetailFixture from './fixtures/index_detail'; import indexDetailAdvancedFixture from './fixtures/index_detail_advanced'; diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/indices.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/indices.js index 9e4b072796590..085e0354ee3eb 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/indices.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/indices.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import relocatingShardsFixture from './fixtures/indices_shards_relocating'; import relocationShardsAllFixture from './fixtures/indices_shards_relocating_all'; import indicesRedClusterFixture from './fixtures/indices_red_cluster'; diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/node_detail.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/node_detail.js index 35fc50c14d278..e23b5db8db225 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/node_detail.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/node_detail.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import nodeDetailFixture from './fixtures/node_detail'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/node_detail_advanced.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/node_detail_advanced.js index 14911878dfb6d..ec182a1d1b518 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/node_detail_advanced.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/node_detail_advanced.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import nodeDetailFixture from './fixtures/node_detail_advanced'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/nodes.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/nodes.js index f1a978a8bdab5..7d3bb23ebfbcf 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/nodes.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/nodes.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import nodesListingFixtureGreen from './fixtures/nodes_listing_green'; import nodesListingFixtureRed from './fixtures/nodes_listing_red'; import nodesListingFixtureCgroup from './fixtures/nodes_listing_cgroup'; diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/overview.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/overview.js index 170fe101433b4..cc5ab081125ec 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/overview.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import overviewFixtureGreenPlatinum from './fixtures/overview_green_platinum'; import overviewFixtureRedPlatinum from './fixtures/overview_red_platinum'; diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/check_cluster.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/check_cluster.js index 0c17f08ff3368..521d201c9d1d7 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/check_cluster.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/check_cluster.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/check_nodes.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/check_nodes.js index 0c500610b1ed6..c383a65f4a154 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/check_nodes.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/check_nodes.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/set_collection_enabled.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/set_collection_enabled.js index 7b5c73f029a44..9b85887311e9c 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/set_collection_enabled.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/set_collection_enabled.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/set_collection_interval.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/set_collection_interval.js index ac469fb3e8869..a58cc01c38719 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/set_collection_interval.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch_settings/set_collection_interval.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/monitoring/kibana/instance.js b/x-pack/test/api_integration/apis/monitoring/kibana/instance.js index e0a67839e2969..e2906e74c5170 100644 --- a/x-pack/test/api_integration/apis/monitoring/kibana/instance.js +++ b/x-pack/test/api_integration/apis/monitoring/kibana/instance.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import instanceFixture from './fixtures/instance'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/kibana/listing.js b/x-pack/test/api_integration/apis/monitoring/kibana/listing.js index 013f20486d9ae..c6db6171d530b 100644 --- a/x-pack/test/api_integration/apis/monitoring/kibana/listing.js +++ b/x-pack/test/api_integration/apis/monitoring/kibana/listing.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import listingFixture from './fixtures/listing'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/kibana/overview.js b/x-pack/test/api_integration/apis/monitoring/kibana/overview.js index c3e3339623443..42c0def5050fa 100644 --- a/x-pack/test/api_integration/apis/monitoring/kibana/overview.js +++ b/x-pack/test/api_integration/apis/monitoring/kibana/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import overviewFixture from './fixtures/overview'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/logstash/node_detail.js b/x-pack/test/api_integration/apis/monitoring/logstash/node_detail.js index bbc385e3ba1c9..92f093e8a3346 100644 --- a/x-pack/test/api_integration/apis/monitoring/logstash/node_detail.js +++ b/x-pack/test/api_integration/apis/monitoring/logstash/node_detail.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import nodeDetailFixture from './fixtures/node_detail'; import nodeDetailAdvancedFixture from './fixtures/node_detail_advanced'; diff --git a/x-pack/test/api_integration/apis/monitoring/logstash/nodes.js b/x-pack/test/api_integration/apis/monitoring/logstash/nodes.js index 7709eaeae0c6b..ddc60e780e863 100644 --- a/x-pack/test/api_integration/apis/monitoring/logstash/nodes.js +++ b/x-pack/test/api_integration/apis/monitoring/logstash/nodes.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import nodesFixture from './fixtures/nodes'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/logstash/overview.js b/x-pack/test/api_integration/apis/monitoring/logstash/overview.js index b5053336f0722..9c432486c4615 100644 --- a/x-pack/test/api_integration/apis/monitoring/logstash/overview.js +++ b/x-pack/test/api_integration/apis/monitoring/logstash/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import overviewFixture from './fixtures/overview.json'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/standalone_cluster/cluster.js b/x-pack/test/api_integration/apis/monitoring/standalone_cluster/cluster.js index ed753e8dea9ad..d9ff5303be654 100644 --- a/x-pack/test/api_integration/apis/monitoring/standalone_cluster/cluster.js +++ b/x-pack/test/api_integration/apis/monitoring/standalone_cluster/cluster.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import clusterFixture from './fixtures/cluster'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/monitoring/standalone_cluster/clusters.js b/x-pack/test/api_integration/apis/monitoring/standalone_cluster/clusters.js index e4a99127c7bb3..33fcdc6f9b5a9 100644 --- a/x-pack/test/api_integration/apis/monitoring/standalone_cluster/clusters.js +++ b/x-pack/test/api_integration/apis/monitoring/standalone_cluster/clusters.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import clustersFixture from './fixtures/clusters'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/security/basic_login.js b/x-pack/test/api_integration/apis/security/basic_login.js index add872ee66dd0..39c6c0ef0a135 100644 --- a/x-pack/test/api_integration/apis/security/basic_login.js +++ b/x-pack/test/api_integration/apis/security/basic_login.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import request from 'request'; export default function ({ getService }) { diff --git a/x-pack/test/api_integration/apis/security/roles.js b/x-pack/test/api_integration/apis/security/roles.js index 28e6f517d8e87..46eb56ab5602e 100644 --- a/x-pack/test/api_integration/apis/security/roles.js +++ b/x-pack/test/api_integration/apis/security/roles.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const es = getService('es'); diff --git a/x-pack/test/api_integration/apis/uptime/get_all_pings.js b/x-pack/test/api_integration/apis/uptime/get_all_pings.js index a3cf2774fb022..d2c7cd3b3f5c3 100644 --- a/x-pack/test/api_integration/apis/uptime/get_all_pings.js +++ b/x-pack/test/api_integration/apis/uptime/get_all_pings.js @@ -5,7 +5,7 @@ */ import moment from 'moment'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/uptime/graphql/doc_count.js b/x-pack/test/api_integration/apis/uptime/graphql/doc_count.js index 9935151b36a7e..087697377ce81 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/doc_count.js +++ b/x-pack/test/api_integration/apis/uptime/graphql/doc_count.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getDocCountQueryString } from '../../../../../plugins/uptime/public/components/queries/empty_state/get_doc_count'; import docCount from './fixtures/doc_count'; diff --git a/x-pack/test/api_integration/apis/uptime/graphql/error_list.js b/x-pack/test/api_integration/apis/uptime/graphql/error_list.js index 3aaf7798d1fae..862cfefec4df0 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/error_list.js +++ b/x-pack/test/api_integration/apis/uptime/graphql/error_list.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getErrorListQueryString } from '../../../../../plugins/uptime/public/components/queries/error_list/get_error_list'; import errorList from './fixtures/error_list'; import errorListFilteredById from './fixtures/error_list_filtered_by_id'; diff --git a/x-pack/test/api_integration/apis/uptime/graphql/filter_bar.js b/x-pack/test/api_integration/apis/uptime/graphql/filter_bar.js index fdbade1b15909..463b7b9bd9b27 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/filter_bar.js +++ b/x-pack/test/api_integration/apis/uptime/graphql/filter_bar.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getFilterBarQueryString } from '../../../../../plugins/uptime/public/components/queries/filter_bar/get_filter_bar'; import filterList from './fixtures/filter_list'; diff --git a/x-pack/test/api_integration/apis/uptime/graphql/monitor_charts.js b/x-pack/test/api_integration/apis/uptime/graphql/monitor_charts.js index 26e73fca2d80a..8e761557b1c74 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/monitor_charts.js +++ b/x-pack/test/api_integration/apis/uptime/graphql/monitor_charts.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getMonitorChartsQueryString } from '../../../../../plugins/uptime/public/components/queries/monitor_charts/get_monitor_charts'; import monitorCharts from './fixtures/monitor_charts'; import monitorChartsEmptySet from './fixtures/monitor_charts_empty_set'; diff --git a/x-pack/test/api_integration/apis/uptime/graphql/monitor_list.js b/x-pack/test/api_integration/apis/uptime/graphql/monitor_list.js index 1720d1c11db02..6e190195f5208 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/monitor_list.js +++ b/x-pack/test/api_integration/apis/uptime/graphql/monitor_list.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import monitorList from './fixtures/monitor_list'; import monitorListDownFiltered from './fixtures/monitor_list_down_filtered'; import monitorListUpFiltered from './fixtures/monitor_list_up_filtered'; diff --git a/x-pack/test/api_integration/apis/uptime/graphql/monitor_status_bar.js b/x-pack/test/api_integration/apis/uptime/graphql/monitor_status_bar.js index f50e48dafc2d1..15399b058f9b7 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/monitor_status_bar.js +++ b/x-pack/test/api_integration/apis/uptime/graphql/monitor_status_bar.js @@ -5,7 +5,7 @@ */ import { omit } from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; // eslint-disable-next-line max-len import { getMonitorStatusBarQueryString } from '../../../../../plugins/uptime/public/components/queries/monitor_status_bar/get_monitor_status_bar'; import monitorStatus from './fixtures/monitor_status'; diff --git a/x-pack/test/api_integration/apis/uptime/graphql/ping_list.js b/x-pack/test/api_integration/apis/uptime/graphql/ping_list.js index ea44b03fbe81d..89d974353b7f6 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/ping_list.js +++ b/x-pack/test/api_integration/apis/uptime/graphql/ping_list.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getPingsQueryString } from '../../../../../plugins/uptime/public/components/queries/ping_list/get_pings'; import pingList from './fixtures/ping_list'; import pingListCount from './fixtures/ping_list_count'; diff --git a/x-pack/test/api_integration/apis/uptime/graphql/snapshot.js b/x-pack/test/api_integration/apis/uptime/graphql/snapshot.js index f1f98733be4e5..4e656e001ac99 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/snapshot.js +++ b/x-pack/test/api_integration/apis/uptime/graphql/snapshot.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getSnapshotQueryString } from '../../../../../plugins/uptime/public/components/queries/snapshot/get_snapshot'; import snapshot from './fixtures/snapshot'; import snapshotFilteredByDown from './fixtures/snapshot_filtered_by_down'; diff --git a/x-pack/test/api_integration/apis/xpack_main/settings/settings.js b/x-pack/test/api_integration/apis/xpack_main/settings/settings.js index 9f7055c7b8332..3a19aa10e305d 100644 --- a/x-pack/test/api_integration/apis/xpack_main/settings/settings.js +++ b/x-pack/test/api_integration/apis/xpack_main/settings/settings.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry.js b/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry.js index 08ebc715527bd..3017a35880236 100644 --- a/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry.js +++ b/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import multiClusterFixture from './fixtures/multicluster'; import basicClusterFixture from './fixtures/basiccluster'; diff --git a/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry_local.js b/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry_local.js index 2ee08c3cdfb8e..93671ccdc5fd8 100644 --- a/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry_local.js +++ b/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry_local.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import _ from 'lodash'; /* diff --git a/x-pack/test/functional/apps/canvas/smoke_test.js b/x-pack/test/functional/apps/canvas/smoke_test.js index 45552e1a4067d..b309472f382c6 100644 --- a/x-pack/test/functional/apps/canvas/smoke_test.js +++ b/x-pack/test/functional/apps/canvas/smoke_test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { parse } from 'url'; export default function canvasSmokeTest({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js index 8a70a2c64c5dd..9275a802bfaa7 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); diff --git a/x-pack/test/functional/apps/graph/graph.js b/x-pack/test/functional/apps/graph/graph.js index 655feb529cfad..b7e5e44450973 100644 --- a/x-pack/test/functional/apps/graph/graph.js +++ b/x-pack/test/functional/apps/graph/graph.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; // import { indexBy } from 'lodash'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/logstash/pipeline_create.js b/x-pack/test/functional/apps/logstash/pipeline_create.js index 101f9d3f03876..7c1d1bf13d8e2 100644 --- a/x-pack/test/functional/apps/logstash/pipeline_create.js +++ b/x-pack/test/functional/apps/logstash/pipeline_create.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const browser = getService('browser'); diff --git a/x-pack/test/functional/apps/logstash/pipeline_list.js b/x-pack/test/functional/apps/logstash/pipeline_list.js index 5fd40a0b3a36c..d04f50690368d 100644 --- a/x-pack/test/functional/apps/logstash/pipeline_list.js +++ b/x-pack/test/functional/apps/logstash/pipeline_list.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { omit } from 'lodash'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/maps/add_layer_panel.js b/x-pack/test/functional/apps/maps/add_layer_panel.js index f18ea6fb99719..1bb30477a2a9c 100644 --- a/x-pack/test/functional/apps/maps/add_layer_panel.js +++ b/x-pack/test/functional/apps/maps/add_layer_panel.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects }) { const PageObjects = getPageObjects(['maps', 'common']); diff --git a/x-pack/test/functional/apps/maps/embeddable/dashboard.js b/x-pack/test/functional/apps/maps/embeddable/dashboard.js index f7e35bd5ca995..0fecfd71f3d14 100644 --- a/x-pack/test/functional/apps/maps/embeddable/dashboard.js +++ b/x-pack/test/functional/apps/maps/embeddable/dashboard.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['common', 'dashboard', 'maps']); diff --git a/x-pack/test/functional/apps/maps/es_geo_grid_source.js b/x-pack/test/functional/apps/maps/es_geo_grid_source.js index a4663256fc340..1ee034d07689c 100644 --- a/x-pack/test/functional/apps/maps/es_geo_grid_source.js +++ b/x-pack/test/functional/apps/maps/es_geo_grid_source.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects, getService }) { diff --git a/x-pack/test/functional/apps/maps/es_search_source.js b/x-pack/test/functional/apps/maps/es_search_source.js index c9745ebbecfa2..a20f411486373 100644 --- a/x-pack/test/functional/apps/maps/es_search_source.js +++ b/x-pack/test/functional/apps/maps/es_search_source.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['maps']); diff --git a/x-pack/test/functional/apps/maps/joins.js b/x-pack/test/functional/apps/maps/joins.js index 7976225405993..4eae5e85dbecf 100644 --- a/x-pack/test/functional/apps/maps/joins.js +++ b/x-pack/test/functional/apps/maps/joins.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; const JOIN_PROPERTY_NAME = '__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name'; const EXPECTED_JOIN_VALUES = { diff --git a/x-pack/test/functional/apps/maps/layer_errors.js b/x-pack/test/functional/apps/maps/layer_errors.js index 532cba839127e..1fe9778a44db3 100644 --- a/x-pack/test/functional/apps/maps/layer_errors.js +++ b/x-pack/test/functional/apps/maps/layer_errors.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects }) { diff --git a/x-pack/test/functional/apps/maps/sample_data.js b/x-pack/test/functional/apps/maps/sample_data.js index 7e871d01f9fd8..76ddeab4ae155 100644 --- a/x-pack/test/functional/apps/maps/sample_data.js +++ b/x-pack/test/functional/apps/maps/sample_data.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects, getService, updateBaselines }) { const PageObjects = getPageObjects(['common', 'maps', 'header', 'home', 'timePicker']); diff --git a/x-pack/test/functional/apps/maps/saved_object_management.js b/x-pack/test/functional/apps/maps/saved_object_management.js index e093d86ebde8b..a31bc2bdd569c 100644 --- a/x-pack/test/functional/apps/maps/saved_object_management.js +++ b/x-pack/test/functional/apps/maps/saved_object_management.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getPageObjects, getService }) { diff --git a/x-pack/test/functional/apps/monitoring/beats/beat_detail.js b/x-pack/test/functional/apps/monitoring/beats/beat_detail.js index 5ca033549f937..d352579e01160 100644 --- a/x-pack/test/functional/apps/monitoring/beats/beat_detail.js +++ b/x-pack/test/functional/apps/monitoring/beats/beat_detail.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/beats/cluster.js b/x-pack/test/functional/apps/monitoring/beats/cluster.js index 949feef987851..8ee93066254d5 100644 --- a/x-pack/test/functional/apps/monitoring/beats/cluster.js +++ b/x-pack/test/functional/apps/monitoring/beats/cluster.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/beats/listing.js b/x-pack/test/functional/apps/monitoring/beats/listing.js index 0a0148aee69c6..700b5d593ecb8 100644 --- a/x-pack/test/functional/apps/monitoring/beats/listing.js +++ b/x-pack/test/functional/apps/monitoring/beats/listing.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/beats/overview.js b/x-pack/test/functional/apps/monitoring/beats/overview.js index 049ffc963c4f9..1c8b70a462843 100644 --- a/x-pack/test/functional/apps/monitoring/beats/overview.js +++ b/x-pack/test/functional/apps/monitoring/beats/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/cluster/alerts.js b/x-pack/test/functional/apps/monitoring/cluster/alerts.js index 8cc6b3e5f089e..0a2ffb90c536d 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/alerts.js +++ b/x-pack/test/functional/apps/monitoring/cluster/alerts.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; const HIGH_ALERT_MESSAGE = 'High severity alert'; diff --git a/x-pack/test/functional/apps/monitoring/cluster/list.js b/x-pack/test/functional/apps/monitoring/cluster/list.js index aa2e8ff8ee045..c3eb509c6eed8 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/list.js +++ b/x-pack/test/functional/apps/monitoring/cluster/list.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/cluster/overview.js b/x-pack/test/functional/apps/monitoring/cluster/overview.js index bfbd1b69a9e54..8242150e404eb 100644 --- a/x-pack/test/functional/apps/monitoring/cluster/overview.js +++ b/x-pack/test/functional/apps/monitoring/cluster/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js b/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js index dd0ea8f03ab41..718d4c012989b 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js b/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js index 2dea5db65598e..fc3669079dbce 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js b/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js index 1cb6902948a16..46fdd8d3921a3 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js index f57677411c210..357874d501417 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js b/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js index 1597bc6be046d..3f90c6a096e90 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js b/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js index dd106082d033a..e22d160f4faf6 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/shards.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/enable_monitoring/index.js b/x-pack/test/functional/apps/monitoring/enable_monitoring/index.js index efb9fecb37445..2cdecc58266a6 100644 --- a/x-pack/test/functional/apps/monitoring/enable_monitoring/index.js +++ b/x-pack/test/functional/apps/monitoring/enable_monitoring/index.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['monitoring', 'common', 'header']); diff --git a/x-pack/test/functional/apps/monitoring/kibana/instance.js b/x-pack/test/functional/apps/monitoring/kibana/instance.js index c6f6fb4aaa5c4..33448fc4b206a 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/instance.js +++ b/x-pack/test/functional/apps/monitoring/kibana/instance.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/kibana/instances.js b/x-pack/test/functional/apps/monitoring/kibana/instances.js index b79f67152b857..28bf108d59f24 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/instances.js +++ b/x-pack/test/functional/apps/monitoring/kibana/instances.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/kibana/overview.js b/x-pack/test/functional/apps/monitoring/kibana/overview.js index 90a8bebe90215..7282e48fc8a91 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/overview.js +++ b/x-pack/test/functional/apps/monitoring/kibana/overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js index 613a3d87efe7c..4d2a7dbc68887 100644 --- a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js +++ b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { getLifecycleMethods } from '../_get_lifecycle_methods'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js index c0012ee04ab71..5546cd9311ef1 100644 --- a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js +++ b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { indexBy } from 'lodash'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/security/doc_level_security_roles.js b/x-pack/test/functional/apps/security/doc_level_security_roles.js index 2229c8c083650..9ea1e30358ff3 100644 --- a/x-pack/test/functional/apps/security/doc_level_security_roles.js +++ b/x-pack/test/functional/apps/security/doc_level_security_roles.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { indexBy } from 'lodash'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/security/field_level_security.js b/x-pack/test/functional/apps/security/field_level_security.js index eb9fdd2a5084d..4ce68580334a2 100644 --- a/x-pack/test/functional/apps/security/field_level_security.js +++ b/x-pack/test/functional/apps/security/field_level_security.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { indexBy } from 'lodash'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/security/management.js b/x-pack/test/functional/apps/security/management.js index 053f805d4e46c..aa9ae9f1ed48c 100644 --- a/x-pack/test/functional/apps/security/management.js +++ b/x-pack/test/functional/apps/security/management.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { USERS_PATH, EDIT_USERS_PATH, diff --git a/x-pack/test/functional/apps/security/rbac_phase1.js b/x-pack/test/functional/apps/security/rbac_phase1.js index e25dcec464a73..e8c70b0d96445 100644 --- a/x-pack/test/functional/apps/security/rbac_phase1.js +++ b/x-pack/test/functional/apps/security/rbac_phase1.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { indexBy } from 'lodash'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/security/secure_roles_perm.js b/x-pack/test/functional/apps/security/secure_roles_perm.js index 47502e7fc72a4..fb5effa627756 100644 --- a/x-pack/test/functional/apps/security/secure_roles_perm.js +++ b/x-pack/test/functional/apps/security/secure_roles_perm.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { indexBy } from 'lodash'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/security/security.js b/x-pack/test/functional/apps/security/security.js index ba4ee6fb7b29d..38d4d6a393981 100644 --- a/x-pack/test/functional/apps/security/security.js +++ b/x-pack/test/functional/apps/security/security.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/security/user_email.js b/x-pack/test/functional/apps/security/user_email.js index 3312171786683..d4828b61053d6 100644 --- a/x-pack/test/functional/apps/security/user_email.js +++ b/x-pack/test/functional/apps/security/user_email.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { indexBy } from 'lodash'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/security/users.js b/x-pack/test/functional/apps/security/users.js index 53c4df274c87e..b8fabf534f6e2 100644 --- a/x-pack/test/functional/apps/security/users.js +++ b/x-pack/test/functional/apps/security/users.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { indexBy } from 'lodash'; export default function ({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/apps/watcher/watcher_test.js b/x-pack/test/functional/apps/watcher/watcher_test.js index 1af7da85036bf..c07ab3b7155d7 100644 --- a/x-pack/test/functional/apps/watcher/watcher_test.js +++ b/x-pack/test/functional/apps/watcher/watcher_test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { indexBy } from 'lodash'; const watchID = 'watchID'; diff --git a/x-pack/test/functional/page_objects/accountsetting_page.js b/x-pack/test/functional/page_objects/accountsetting_page.js index 90f3bc5bc181b..a49b9544ce7e3 100644 --- a/x-pack/test/functional/page_objects/accountsetting_page.js +++ b/x-pack/test/functional/page_objects/accountsetting_page.js @@ -5,7 +5,7 @@ */ //import { map as mapAsync } from 'bluebird'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function AccountSettingProvider({ getService }) { const testSubjects = getService('testSubjects'); diff --git a/x-pack/test/functional/page_objects/rollup_page.js b/x-pack/test/functional/page_objects/rollup_page.js index b722fd17a4167..44eb762fb7082 100644 --- a/x-pack/test/functional/page_objects/rollup_page.js +++ b/x-pack/test/functional/page_objects/rollup_page.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { map as mapAsync } from 'bluebird'; export function RollupPageProvider({ getService, getPageObjects }) { diff --git a/x-pack/test/functional/page_objects/space_selector_page.js b/x-pack/test/functional/page_objects/space_selector_page.js index 9f7ff9ced6b6d..3be1ae174ce46 100644 --- a/x-pack/test/functional/page_objects/space_selector_page.js +++ b/x-pack/test/functional/page_objects/space_selector_page.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function SpaceSelectorPageProvider({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/x-pack/test/functional/page_objects/status_page.js b/x-pack/test/functional/page_objects/status_page.js index 36915dff5dd09..68fc931a9140f 100644 --- a/x-pack/test/functional/page_objects/status_page.js +++ b/x-pack/test/functional/page_objects/status_page.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function StatusPagePageProvider({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/x-pack/test/functional/page_objects/upgrade_assistant.js b/x-pack/test/functional/page_objects/upgrade_assistant.js index f0011b76b2ac4..af9d5ea55cec6 100644 --- a/x-pack/test/functional/page_objects/upgrade_assistant.js +++ b/x-pack/test/functional/page_objects/upgrade_assistant.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function UpgradeAssistantProvider({ getService, getPageObjects }) { const retry = getService('retry'); diff --git a/x-pack/test/functional/services/grok_debugger.js b/x-pack/test/functional/services/grok_debugger.js index c8870e534ce55..48717bee0e3a9 100644 --- a/x-pack/test/functional/services/grok_debugger.js +++ b/x-pack/test/functional/services/grok_debugger.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function GrokDebuggerProvider({ getService }) { const aceEditor = getService('aceEditor'); diff --git a/x-pack/test/functional/services/monitoring/cluster_overview.js b/x-pack/test/functional/services/monitoring/cluster_overview.js index 25c110ef4d9df..83657bd884965 100644 --- a/x-pack/test/functional/services/monitoring/cluster_overview.js +++ b/x-pack/test/functional/services/monitoring/cluster_overview.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; export function MonitoringClusterOverviewProvider({ getService }) { const testSubjects = getService('testSubjects'); diff --git a/x-pack/test/functional/services/pipeline_editor.js b/x-pack/test/functional/services/pipeline_editor.js index ad7b5e7d0147f..804fdf27158fe 100644 --- a/x-pack/test/functional/services/pipeline_editor.js +++ b/x-pack/test/functional/services/pipeline_editor.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { props as propsAsync } from 'bluebird'; export function PipelineEditorProvider({ getService }) { diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js index 0d3180902d550..4bfae4c24a882 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js @@ -5,7 +5,7 @@ */ import _ from 'lodash'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import url from 'url'; import supertestAsPromised from 'supertest-as-promised'; diff --git a/x-pack/test/reporting/api/usage.js b/x-pack/test/reporting/api/usage.js index 0e5004e9c956e..1b70ab9e4547f 100644 --- a/x-pack/test/reporting/api/usage.js +++ b/x-pack/test/reporting/api/usage.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import * as GenerationUrls from './generation_urls'; export default function ({ getService }) { diff --git a/x-pack/test/reporting/functional/reporting.js b/x-pack/test/reporting/functional/reporting.js index 33f064388aa6c..4e1b51ae058e5 100644 --- a/x-pack/test/reporting/functional/reporting.js +++ b/x-pack/test/reporting/functional/reporting.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import path from 'path'; import mkdirp from 'mkdirp'; import fs from 'fs'; diff --git a/x-pack/test/reporting/services/reporting_api.js b/x-pack/test/reporting/services/reporting_api.js index 0c66a77a65fe2..8feb7a70803e2 100644 --- a/x-pack/test/reporting/services/reporting_api.js +++ b/x-pack/test/reporting/services/reporting_api.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { indexTimestamp } from '../../../plugins/reporting/server/lib/esqueue/helpers/index_timestamp'; function removeWhitespace(str) { diff --git a/x-pack/test/saml_api_integration/apis/security/saml_login.js b/x-pack/test/saml_api_integration/apis/security/saml_login.js index fe6f2bf07db02..a664d68d1b2d1 100644 --- a/x-pack/test/saml_api_integration/apis/security/saml_login.js +++ b/x-pack/test/saml_api_integration/apis/security/saml_login.js @@ -8,7 +8,7 @@ import querystring from 'querystring'; import url from 'url'; import { delay } from 'bluebird'; import { getLogoutRequest, getSAMLRequestId, getSAMLResponse } from '../../fixtures/saml_tools'; -import expect from 'expect.js'; +import expect from '@kbn/expect'; import request from 'request'; export default function ({ getService }) { diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts index 82099fe4bd304..b0390af36017a 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts index e82ea7b856a8c..a0e0d21f942dd 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/common/suites/create.ts b/x-pack/test/saved_object_api_integration/common/suites/create.ts index 9a8de7d7f3bd9..8dc73a7b31e4c 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/create.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/common/suites/delete.ts b/x-pack/test/saved_object_api_integration/common/suites/delete.ts index 5e4068f5b795c..229ef4e625baa 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/delete.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/delete.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/common/suites/export.ts b/x-pack/test/saved_object_api_integration/common/suites/export.ts index 1b55245a210c6..58ebf31e5daec 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/export.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/export.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/common/suites/find.ts b/x-pack/test/saved_object_api_integration/common/suites/find.ts index d71a56a79a41b..f00697889a3b3 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/find.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/find.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/common/suites/get.ts b/x-pack/test/saved_object_api_integration/common/suites/get.ts index 1cc36b411c61a..c178a2389986d 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/get.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/get.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/common/suites/import.ts b/x-pack/test/saved_object_api_integration/common/suites/import.ts index 9f45044031e5a..816b68d3eed3f 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/import.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/import.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts index c13a5bf15afe6..0a06ca064beee 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/common/suites/update.ts b/x-pack/test/saved_object_api_integration/common/suites/update.ts index 7fa534e142b3d..e292daa13d122 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/update.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/update.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts index cf794079a42ea..efbc14060c9f2 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SPACES } from '../../common/lib/spaces'; import { TestInvoker } from '../../common/lib/types'; import { bulkCreateTestSuiteFactory } from '../../common/suites/bulk_create'; diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts index 129023130e716..0c29292f293cb 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SPACES } from '../../common/lib/spaces'; import { TestInvoker } from '../../common/lib/types'; import { createTestSuiteFactory } from '../../common/suites/create'; diff --git a/x-pack/test/spaces_api_integration/common/suites/create.ts b/x-pack/test/spaces_api_integration/common/suites/create.ts index 4a8b2bc5c9e8d..6af5afc2530c7 100644 --- a/x-pack/test/spaces_api_integration/common/suites/create.ts +++ b/x-pack/test/spaces_api_integration/common/suites/create.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { getUrlPrefix } from '../lib/space_test_utils'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; diff --git a/x-pack/test/spaces_api_integration/common/suites/delete.ts b/x-pack/test/spaces_api_integration/common/suites/delete.ts index 4ebd26190f9de..2cf2d9388665a 100644 --- a/x-pack/test/spaces_api_integration/common/suites/delete.ts +++ b/x-pack/test/spaces_api_integration/common/suites/delete.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { getUrlPrefix } from '../lib/space_test_utils'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; diff --git a/x-pack/test/spaces_api_integration/common/suites/get.ts b/x-pack/test/spaces_api_integration/common/suites/get.ts index dd9e686de75a1..06fda9313f7a2 100644 --- a/x-pack/test/spaces_api_integration/common/suites/get.ts +++ b/x-pack/test/spaces_api_integration/common/suites/get.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperAgent } from 'superagent'; import { getUrlPrefix } from '../lib/space_test_utils'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; diff --git a/x-pack/test/spaces_api_integration/common/suites/get_all.ts b/x-pack/test/spaces_api_integration/common/suites/get_all.ts index 175fcc8f8bfb8..64acb60308c41 100644 --- a/x-pack/test/spaces_api_integration/common/suites/get_all.ts +++ b/x-pack/test/spaces_api_integration/common/suites/get_all.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { getUrlPrefix } from '../lib/space_test_utils'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; diff --git a/x-pack/test/spaces_api_integration/common/suites/select.ts b/x-pack/test/spaces_api_integration/common/suites/select.ts index b9f67d9f0596a..489dc9f26529b 100644 --- a/x-pack/test/spaces_api_integration/common/suites/select.ts +++ b/x-pack/test/spaces_api_integration/common/suites/select.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { getUrlPrefix } from '../lib/space_test_utils'; diff --git a/x-pack/test/spaces_api_integration/common/suites/update.ts b/x-pack/test/spaces_api_integration/common/suites/update.ts index a0cb1a9441730..88297df311334 100644 --- a/x-pack/test/spaces_api_integration/common/suites/update.ts +++ b/x-pack/test/spaces_api_integration/common/suites/update.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { getUrlPrefix } from '../lib/space_test_utils'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 2e9fc43a6aa62..a22ce122b1766 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -2,7 +2,6 @@ "extends": "../tsconfig.json", "compilerOptions": { "types": [ - "@kbn/test/types/expect.js", "mocha", "node" ] diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js index 56f1171de944d..ae48c38a23fe6 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js @@ -5,7 +5,7 @@ */ -import expect from 'expect.js'; +import expect from '@kbn/expect'; import { ReindexStatus, REINDEX_OP_TYPE } from '../../../plugins/upgrade_assistant/common/types'; diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index dd3ab033718b8..979d0737d03a9 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -32,8 +32,7 @@ }, "types": [ "node", - "jest", - "@kbn/test/types/expect.js" + "jest" ] } } diff --git a/yarn.lock b/yarn.lock index 02a508c614501..1bd2096868381 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9714,11 +9714,6 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -expect.js@0.3.1, expect.js@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.3.1.tgz#b0a59a0d2eff5437544ebf0ceaa6015841d09b5b" - integrity sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s= - expect.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.2.0.tgz#1028533d2c1c363f74a6796ff57ec0520ded2be1" From dfeb12f50200783a8bcb8a783d584c9b85fd1984 Mon Sep 17 00:00:00 2001 From: Spencer Date: Mon, 25 Mar 2019 11:00:57 -0700 Subject: [PATCH 25/96] [ci] rebuild kbn-pm distributatble to ensure it is up-to-date (#33752) --- src/dev/ci_setup/setup.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/dev/ci_setup/setup.sh b/src/dev/ci_setup/setup.sh index c5ab06f40983e..179fac9aa8a74 100755 --- a/src/dev/ci_setup/setup.sh +++ b/src/dev/ci_setup/setup.sh @@ -144,3 +144,19 @@ if [ "$GIT_CHANGES" ]; then echo -e "$GIT_CHANGES\n" exit 1 fi + +### +### rebuild kbn-pm distributable to ensure it's not out of date +### +echo " -- building kbn-pm distributable" +yarn kbn run build -i @kbn/pm + +### +### verify no git modifications +### +GIT_CHANGES="$(git ls-files --modified)" +if [ "$GIT_CHANGES" ]; then + echo -e "\n${RED}ERROR: 'yarn kbn run build -i @kbn/pm' caused changes to the following files:${C_RESET}\n" + echo -e "$GIT_CHANGES\n" + exit 1 +fi From 3f9c36bb2511f3bc30d1906aeae6906b512b06cb Mon Sep 17 00:00:00 2001 From: Brandon Kobel Date: Mon, 25 Mar 2019 11:03:25 -0700 Subject: [PATCH 26/96] Fixing the regex that is used to validate the Space ID (#33716) * Fixing the regex that is used to validate the Space id * Adding basic jest tests for the space schema's ID --- .../spaces/server/lib/space_schema.test.ts | 64 +++++++++++++++++++ .../plugins/spaces/server/lib/space_schema.ts | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/spaces/server/lib/space_schema.test.ts diff --git a/x-pack/plugins/spaces/server/lib/space_schema.test.ts b/x-pack/plugins/spaces/server/lib/space_schema.test.ts new file mode 100644 index 0000000000000..6ca37affb8487 --- /dev/null +++ b/x-pack/plugins/spaces/server/lib/space_schema.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { spaceSchema } from './space_schema'; + +const defaultProperties = { + id: 'foo', + name: 'foo', +}; + +describe('#id', () => { + test('is optional', () => { + const result = spaceSchema.validate({ + ...defaultProperties, + id: undefined, + }); + expect(result.error).toBeNull(); + }); + + test('allows lowercase a-z, 0-9, "_" and "-"', () => { + const result = spaceSchema.validate({ + ...defaultProperties, + id: 'abcdefghijklmnopqrstuvwxyz0123456789_-', + }); + expect(result.error).toBeNull(); + }); + + test(`doesn't allow uppercase`, () => { + const result = spaceSchema.validate({ + ...defaultProperties, + id: 'Foo', + }); + expect(result.error).toMatchInlineSnapshot( + `[ValidationError: child "id" fails because ["id" with value "Foo" fails to match the lower case, a-z, 0-9, "_", and "-" are allowed pattern]]` + ); + }); + + test(`doesn't allow an empty string`, () => { + const result = spaceSchema.validate({ + ...defaultProperties, + id: '', + }); + expect(result.error).toMatchInlineSnapshot( + `[ValidationError: child "id" fails because ["id" is not allowed to be empty]]` + ); + }); + + ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '+', ',', '.', '/', '?'].forEach( + invalidCharacter => { + test(`doesn't allow ${invalidCharacter}`, () => { + const result = spaceSchema.validate({ + ...defaultProperties, + id: `foo-${invalidCharacter}`, + }); + expect(result.error).toMatchObject({ + message: `child "id" fails because ["id" with value "foo-${invalidCharacter}" fails to match the lower case, a-z, 0-9, "_", and "-" are allowed pattern]`, + }); + }); + } + ); +}); diff --git a/x-pack/plugins/spaces/server/lib/space_schema.ts b/x-pack/plugins/spaces/server/lib/space_schema.ts index 3343a05a9ae58..d27a855e0f917 100644 --- a/x-pack/plugins/spaces/server/lib/space_schema.ts +++ b/x-pack/plugins/spaces/server/lib/space_schema.ts @@ -8,7 +8,7 @@ import Joi from 'joi'; import { MAX_SPACE_INITIALS } from '../../common/constants'; export const spaceSchema = Joi.object({ - id: Joi.string().regex(/[a-z0-9_\-]*/, `lower case, a-z, 0-9, "_", and "-" are allowed`), + id: Joi.string().regex(/^[a-z0-9_\-]+$/, `lower case, a-z, 0-9, "_", and "-" are allowed`), name: Joi.string().required(), description: Joi.string().allow(''), initials: Joi.string().max(MAX_SPACE_INITIALS), From 5ed923e91e33d3c06234fbc221fe17f24c17aa4c Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 25 Mar 2019 14:36:40 -0400 Subject: [PATCH 27/96] Ensure the pipelines page utilizes reactNodeId (#33798) --- .../plugins/monitoring/public/views/logstash/pipelines/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/monitoring/public/views/logstash/pipelines/index.js b/x-pack/plugins/monitoring/public/views/logstash/pipelines/index.js index 058b9127c82ab..044f0dc2434b9 100644 --- a/x-pack/plugins/monitoring/public/views/logstash/pipelines/index.js +++ b/x-pack/plugins/monitoring/public/views/logstash/pipelines/index.js @@ -72,6 +72,7 @@ uiRoutes title: 'Logstash Pipelines', storageKey: 'logstash.pipelines', getPageData, + reactNodeId: 'monitoringLogstashPipelinesApp', $scope, $injector }); From 0665508b6530616fb3b0f42c74be8b803f2b24ed Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Mon, 25 Mar 2019 16:23:19 -0400 Subject: [PATCH 28/96] only show charts if cell has been selected (#33680) --- x-pack/plugins/ml/public/explorer/explorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ml/public/explorer/explorer.js b/x-pack/plugins/ml/public/explorer/explorer.js index d93fd30b284a6..d3a178709fb8e 100644 --- a/x-pack/plugins/ml/public/explorer/explorer.js +++ b/x-pack/plugins/ml/public/explorer/explorer.js @@ -810,7 +810,7 @@ export const Explorer = injectI18n(injectObservablesAsProps( this.setState(stateUpdate); - if (selectedCells !== null || influencersFilterQuery !== undefined) { + if (selectedCells !== null) { this.updateCharts( stateUpdate.anomalyChartRecords, timerange.earliestMs, timerange.latestMs ); @@ -1274,7 +1274,7 @@ export const Explorer = injectI18n(injectObservablesAsProps( - {anomalyChartRecords.length > 0 && ( + {(anomalyChartRecords.length > 0 && selectedCells !== null) && ( From c6acd796c13f09d6f4b7a1e215d895f4122e5d23 Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Mon, 25 Mar 2019 16:51:27 -0700 Subject: [PATCH 29/96] Added display name and help description to shape arg in progress view (#33819) --- x-pack/plugins/canvas/canvas_plugin_src/uis/views/progress.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/progress.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/progress.js index bd929a32232d4..6b9831d06d597 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/progress.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/progress.js @@ -15,6 +15,8 @@ export const progress = () => ({ args: [ { name: 'shape', + displayName: 'Shape', + help: 'Shape of the progress indicator', argType: 'select', options: { choices: Object.keys(shapes).map(key => ({ From 67acefc28336878ab2d34d662a7dd5a0b1dbd899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Tue, 26 Mar 2019 08:47:29 +0100 Subject: [PATCH 30/96] [CCR] Client integration tests (table lists) (#33525) --- .../auto_follow_pattern_list.test.js | 321 +++++++++++++++ .../follower_indices_list.test.js | 343 ++++++++++++++++ .../__jest__/client_integration/home.test.js | 84 ++++ .../client_integration/test_helpers.js | 212 ++++++++++ .../fixtures/auto_follow_pattern.js | 26 +- .../fixtures/follower_index.js | 177 +++++--- .../auto_follow_pattern_delete_provider.js | 1 + .../auto_follow_pattern_indices_preview.js | 2 +- .../follower_index_pause_provider.js | 1 + .../follower_index_resume_provider.js | 1 + .../follower_index_unfollow_provider.js | 1 + .../public/app/components/section_error.js | 3 +- .../public/app/components/section_loading.js | 3 +- .../auto_follow_pattern_list.js | 26 +- .../auto_follow_pattern_table.js | 1 + .../components/detail_panel/detail_panel.js | 378 +++++++++--------- .../components/context_menu/context_menu.js | 2 +- .../components/detail_panel/detail_panel.js | 198 ++++----- .../follower_indices_table.js | 5 +- .../follower_indices_list.js | 30 +- .../public/app/sections/home/home.js | 4 +- .../job_create.test_helpers.js | 2 +- .../sections/job_list/job_list.test.js | 18 - .../translations/translations/zh-CN.json | 1 - x-pack/test_utils/index.js | 3 +- x-pack/test_utils/lib/index.js | 1 + x-pack/test_utils/lib/strings.js | 2 +- x-pack/test_utils/lib/utils.js | 8 + x-pack/test_utils/testbed/testbed.js | 77 +++- 29 files changed, 1513 insertions(+), 418 deletions(-) create mode 100644 x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js create mode 100644 x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js create mode 100644 x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js create mode 100644 x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js create mode 100644 x-pack/test_utils/lib/utils.js diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js new file mode 100644 index 0000000000000..f9933cd60f1ca --- /dev/null +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js @@ -0,0 +1,321 @@ +/* + * 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 sinon from 'sinon'; + +import { initTestBed, mockAllHttpRequests, nextTick, getRandomString, findTestSubject } from './test_helpers'; +import { AutoFollowPatternList } from '../../public/app/sections/home/auto_follow_pattern_list'; +import { getAutoFollowPatternClientMock } from '../../fixtures/auto_follow_pattern'; + +jest.mock('ui/chrome', () => ({ + addBasePath: () => 'api/cross_cluster_replication', + breadcrumbs: { set: () => {} }, +})); + +jest.mock('ui/index_patterns', () => { + const { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } = require.requireActual('../../../../../src/legacy/ui/public/index_patterns/constants'); // eslint-disable-line max-len + return { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE }; +}); + +describe('', () => { + let server; + let find; + let exists; + let component; + let getMetadataFromEuiTable; + let getUserActions; + let tableCellsValues; + let rows; + let updateHttpMockResponse; + + beforeEach(() => { + server = sinon.fakeServer.create(); + server.respondImmediately = true; + (updateHttpMockResponse = mockAllHttpRequests(server)); + }); + + describe('on component mount', () => { + beforeEach(async () => { + ({ exists } = initTestBed(AutoFollowPatternList)); + }); + + test('should show a loading indicator on component', async () => { + expect(exists('ccrAutoFollowPatternLoading')).toBe(true); + }); + }); + + describe('when there are no auto-follow patterns', () => { + beforeEach(async () => { + ({ exists, component } = initTestBed(AutoFollowPatternList)); + + await nextTick(); // We need to wait next tick for the mock server response to comes in + component.update(); + }); + + test('should display an empty prompt', async () => { + expect(exists('ccrAutoFollowPatternEmptyPrompt')).toBe(true); + }); + + test('should have a button to create a follower index', async () => { + expect(exists('ccrCreateAutoFollowPatternButton')).toBe(true); + }); + }); + + describe('when there are auto-follow patterns', async () => { + // For deterministic tests, we need to make sure that autoFollowPattern1 comes before autoFollowPattern2 + // in the table list that is rendered. As the table orders alphabetically by index name + // we prefix the random name to make sure that autoFollowPattern1 comes before autoFollowPattern2 + const testPrefix = 'prefix_'; + const testSuffix = '_suffix'; + + const autoFollowPattern1 = getAutoFollowPatternClientMock({ + name: `a${getRandomString()}`, + followIndexPattern: `${testPrefix}{{leader_index}}${testSuffix}` + }); + const autoFollowPattern2 = getAutoFollowPatternClientMock({ + name: `b${getRandomString()}`, + followIndexPattern: '{{leader_index}}' // no prefix nor suffix + }); + const autoFollowPatterns = [autoFollowPattern1, autoFollowPattern2]; + + let selectAutoFollowPatternAt; + let clickBulkDeleteButton; + let clickConfirmModalDeleteAutoFollowPattern; + let clickRowActionButtonAt; + let clickAutoFollowPatternAt; + + beforeEach(async () => { + updateHttpMockResponse('loadAutoFollowPatterns', { patterns: autoFollowPatterns }); + + // Mount the component + ({ + find, + exists, + component, + getMetadataFromEuiTable, + getUserActions, + } = initTestBed(AutoFollowPatternList)); + + await nextTick(); // Make sure that the Http request is fulfilled + component.update(); + + ({ + selectAutoFollowPatternAt, + clickBulkDeleteButton, + clickConfirmModalDeleteAutoFollowPattern, + clickRowActionButtonAt, + clickAutoFollowPatternAt, + } = getUserActions('autoFollowPatternList')); + + // Read the index list table + ({ tableCellsValues, rows } = getMetadataFromEuiTable('ccrAutoFollowPatternListTable')); + }); + + afterEach(async () => { + // The updates are not all synchronouse + // We need to wait for all the updates to ran before unmounting our component + await nextTick(100); + }); + + test('should not display the empty prompt', () => { + expect(exists('ccrFollowerIndexEmptyPrompt')).toBe(false); + }); + + test('should have a button to create an auto-follow pattern', () => { + expect(exists('ccrCreateAutoFollowPatternButton')).toBe(true); + }); + + test('should list the auto-follow patterns in the table', () => { + expect(tableCellsValues.length).toEqual(autoFollowPatterns.length); + expect(tableCellsValues).toEqual([ + [ '', // Empty because the first column is the checkbox to select row + autoFollowPattern1.name, + autoFollowPattern1.remoteCluster, + autoFollowPattern1.leaderIndexPatterns.join(', '), + testPrefix, + testSuffix, + '' // Empty because the last column is for the "actions" on the resource + ], [ '', + autoFollowPattern2.name, + autoFollowPattern2.remoteCluster, + autoFollowPattern2.leaderIndexPatterns.join(', '), + '', // no prefix + '', // no suffix + '' ] + ]); + }); + + describe('bulk delete button', () => { + test('should be visible when an auto-follow pattern is selected', () => { + expect(exists('ccrAutoFollowPatternListBulkDeleteActionButton')).toBe(false); + + selectAutoFollowPatternAt(0); + + expect(exists('ccrAutoFollowPatternListBulkDeleteActionButton')).toBe(true); + }); + + test('should update the button label according to the number of patterns selected', () => { + selectAutoFollowPatternAt(0); // 1 auto-follow pattern selected + expect(find('ccrAutoFollowPatternListBulkDeleteActionButton').text()).toEqual('Delete auto-follow pattern'); + + selectAutoFollowPatternAt(1); // 2 auto-follow patterns selected + expect(find('ccrAutoFollowPatternListBulkDeleteActionButton').text()).toEqual('Delete auto-follow patterns'); + }); + + test('should open a confirmation modal when clicking the delete button', () => { + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(false); + + selectAutoFollowPatternAt(0); + clickBulkDeleteButton(); + + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(true); + }); + + test('should remove the auto-follow pattern from the table after delete is complete', async () => { + // Make sure that we have our 2 auto-follow patterns in the table + expect(rows.length).toBe(2); + + // We wil delete the *first* auto-follow pattern in the table + updateHttpMockResponse('deleteAutoFollowPattern', { itemsDeleted: [autoFollowPattern1.name] }); + + selectAutoFollowPatternAt(0); + clickBulkDeleteButton(); + clickConfirmModalDeleteAutoFollowPattern(); + + await nextTick(); + component.update(); + + ({ rows } = getMetadataFromEuiTable('ccrAutoFollowPatternListTable')); + + expect(rows.length).toBe(1); + expect(rows[0].columns[1].value).toEqual(autoFollowPattern2.name); + }); + }); + + describe('table row actions', () => { + test('should have a "delete" and an "edit" action button on each row', () => { + const indexLastColumn = rows[0].columns.length - 1; + const tableCellActions = rows[0].columns[indexLastColumn].reactWrapper; + + const deleteButton = findTestSubject(tableCellActions, 'ccrAutoFollowPatternListDeleteActionButton'); + const editButton = findTestSubject(tableCellActions, 'ccrAutoFollowPatternListEditActionButton'); + + expect(deleteButton.length).toBe(1); + expect(editButton.length).toBe(1); + }); + + test('should open a confirmation modal when clicking on "delete" button', async () => { + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(false); + + clickRowActionButtonAt(0, 'delete'); + + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(true); + }); + }); + + describe('detail panel', () => { + test('should open a detail panel when clicking on a follower index', () => { + expect(exists('ccrAutoFollowPatternDetailsFlyout')).toBe(false); + + clickAutoFollowPatternAt(0); + + expect(exists('ccrAutoFollowPatternDetailsFlyout')).toBe(true); + }); + + test('should set the title the index that has been selected', () => { + clickAutoFollowPatternAt(0); // Open the detail panel + expect(find('autoFollowPatternDetailsFlyoutTitle').text()).toEqual(autoFollowPattern1.name); + }); + + test('should have a "settings" section', () => { + clickAutoFollowPatternAt(0); + expect(find('ccrAutoFollowPatternDetailPanelSettingsSection').find('h3').text()).toEqual('Settings'); + expect(exists('ccrAutoFollowPatternDetailPanelSettingsValues')).toBe(true); + }); + + test('should set the correct follower index settings values', () => { + clickAutoFollowPatternAt(0); + + expect(find('ccrAutoFollowPatternDetailRemoteCluster').text()).toEqual(autoFollowPattern1.remoteCluster); + expect(find('ccrAutoFollowPatternDetailLeaderIndexPatterns').text()).toEqual(autoFollowPattern1.leaderIndexPatterns.join(', ')); + expect(find('ccrAutoFollowPatternDetailPatternPrefix').text()).toEqual(testPrefix); + expect(find('ccrAutoFollowPatternDetailPatternSuffix').text()).toEqual(testSuffix); + }); + + test('should have a default value when there are no prefix or no suffix', () => { + clickAutoFollowPatternAt(1); // Does not have prefix and suffix + + expect(find('ccrAutoFollowPatternDetailPatternPrefix').text()).toEqual('No prefix'); + expect(find('ccrAutoFollowPatternDetailPatternSuffix').text()).toEqual('No suffix'); + }); + + test('should show a preview of the indices that might be generated by the auto-follow pattern', () => { + clickAutoFollowPatternAt(0); + const detailPanel = find('ccrAutoFollowPatternDetailsFlyout'); + const indicesPreview = findTestSubject(detailPanel, 'ccrAutoFollowPatternIndexPreview'); + + expect(exists('ccrAutoFollowPatternDetailPanelIndicesPreviewSection')).toBe(true); + expect(indicesPreview.length).toBe(3); + }); + + test('should have a link to view the indices in Index Management', () => { + clickAutoFollowPatternAt(0); + expect(exists('ccrAutoFollowPatternDetailsViewIndexManagementButton')).toBe(true); + expect(find('ccrAutoFollowPatternDetailsViewIndexManagementButton').text()).toBe('View your follower indices in Index Management'); + }); + + test('should have a "close", "delete" and "edit" button in the footer', () => { + clickAutoFollowPatternAt(0); + expect(exists('ccrAutoFollowPatternDetailsFlyoutCloseButton')).toBe(true); + expect(exists('ccrAutoFollowPatternDetailsDeleteActionButton')).toBe(true); + expect(exists('ccrAutoFollowPatternDetailsEditActionButton')).toBe(true); + }); + + test('should close the detail panel when clicking the "close" button', () => { + clickAutoFollowPatternAt(0); // open the detail panel + expect(exists('ccrAutoFollowPatternDetailsFlyout')).toBe(true); + + find('ccrAutoFollowPatternDetailsFlyoutCloseButton').simulate('click'); // close the detail panel + + expect(exists('ccrAutoFollowPatternDetailsFlyout')).toBe(false); + }); + + test('should open a confirmation modal when clicking the "delete" button', () => { + clickAutoFollowPatternAt(0); + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(false); + + find('ccrAutoFollowPatternDetailsDeleteActionButton').simulate('click'); + + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(true); + }); + + test('should display the recent errors', async () => { + const message = 'bar'; + const recentAutoFollowErrors = [{ + leaderIndex: `${autoFollowPattern1.name}:my-leader-test`, + autoFollowException: { type: 'exception', reason: message } + }, { + leaderIndex: `${autoFollowPattern2.name}:my-leader-test`, + autoFollowException: { type: 'exception', reason: message } + }]; + updateHttpMockResponse('autoFollowStats', { recentAutoFollowErrors }); + + clickAutoFollowPatternAt(0); + expect(exists('ccrAutoFollowPatternDetailErrors')).toBe(false); + + // We select the other auto-follow pattern because the stats are fetched + // each time we change the auto-follow pattern selection + clickAutoFollowPatternAt(1); + await nextTick(); + component.update(); + + expect(exists('ccrAutoFollowPatternDetailErrors')).toBe(true); + expect(exists('ccrAutoFollowPatternDetailsTitleErrors')).toBe(true); + expect(find('ccrAutoFollowPatternDetailRecentError').map(error => error.text())).toEqual([message]); + }); + }); + }); +}); diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js new file mode 100644 index 0000000000000..eb30e796cbaea --- /dev/null +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js @@ -0,0 +1,343 @@ +/* + * 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 sinon from 'sinon'; + +import { initTestBed, mockAllHttpRequests, nextTick, getRandomString } from './test_helpers'; +import { FollowerIndicesList } from '../../public/app/sections/home/follower_indices_list'; +import { getFollowerIndexMock } from '../../fixtures/follower_index'; + +jest.mock('ui/chrome', () => ({ + addBasePath: () => 'api/cross_cluster_replication', + breadcrumbs: { set: () => {} }, +})); + +jest.mock('ui/index_patterns', () => { + const { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } = require.requireActual('../../../../../src/legacy/ui/public/index_patterns/constants'); // eslint-disable-line max-len + return { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE }; +}); + +describe('', () => { + let server; + let find; + let exists; + let component; + let getMetadataFromEuiTable; + let getUserActions; + let tableCellsValues; + let updateHttpMockResponse; + + beforeEach(() => { + server = sinon.fakeServer.create(); + server.respondImmediately = true; + (updateHttpMockResponse = mockAllHttpRequests(server)); + }); + + describe('on component mount', () => { + beforeEach(async () => { + ({ exists } = initTestBed(FollowerIndicesList)); + }); + + test('should show a loading indicator on component', async () => { + expect(exists('ccrFollowerIndexLoading')).toBe(true); + }); + }); + + describe('when there are no follower indices', () => { + beforeEach(async () => { + ({ exists, component } = initTestBed(FollowerIndicesList)); + + await nextTick(); // We need to wait next tick for the mock server response to comes in + component.update(); + }); + + test('should display an empty prompt', async () => { + expect(exists('ccrFollowerIndexEmptyPrompt')).toBe(true); + }); + + test('should have a button to create a follower index', async () => { + expect(exists('ccrFollowerIndexEmptyPromptCreateButton')).toBe(true); + }); + }); + + describe('when there are follower indices', async () => { + // For deterministic tests, we need to make sure that index1 comes before index2 + // in the table list that is rendered. As the table orders alphabetically by index name + // we prefix the random name to make sure that index1 name comes before index2. + const index1 = getFollowerIndexMock({ name: `a${getRandomString()}` }); + const index2 = getFollowerIndexMock({ name: `b${getRandomString()}`, status: 'paused' }); + + const followerIndices = [index1, index2]; + + let selectFollowerIndexAt; + let openContextMenu; + let openTableRowContextMenuAt; + let clickContextMenuButtonAt; + let clickFollowerIndexAt; + + beforeEach(async () => { + updateHttpMockResponse('loadFollowerIndices', { indices: followerIndices }); + + // Mount the component + ({ + find, + exists, + component, + getMetadataFromEuiTable, + getUserActions, + } = initTestBed(FollowerIndicesList)); + + await nextTick(); // Make sure that the Http request is fulfilled + component.update(); + + ({ + selectFollowerIndexAt, + openContextMenu, + openTableRowContextMenuAt, + clickContextMenuButtonAt, + clickFollowerIndexAt, + } = getUserActions('followerIndicesList')); + + // Read the index list table + ({ tableCellsValues } = getMetadataFromEuiTable('ccrFollowerIndexListTable')); + }); + + afterEach(async () => { + // The updates are not all synchronouse + // We need to wait for all the updates to ran before unmounting our component + await nextTick(100); + }); + + test('should not display the empty prompt', () => { + expect(exists('ccrFollowerIndexEmptyPrompt')).toBe(false); + }); + + test('should have a button to create a follower index', () => { + expect(exists('ccrCreateFollowerIndexButton')).toBe(true); + }); + + test('should list the follower indices in the table', () => { + expect(tableCellsValues.length).toEqual(followerIndices.length); + expect(tableCellsValues).toEqual([ + [ '', // Empty because the first column is the checkbox to select row + index1.name, + 'Active', + index1.remoteCluster, + index1.leaderIndex, + '' // Empty because the last column is for the "actions" on the resource + ], [ '', + index2.name, + 'Paused', + index2.remoteCluster, + index2.leaderIndex, + '' ] + ]); + }); + + describe('action menu', () => { + test('should be visible when a follower index is selected', () => { + expect(exists('ccrFollowerIndexListContextMenuButton')).toBe(false); + + selectFollowerIndexAt(0); + + expect(exists('ccrFollowerIndexListContextMenuButton')).toBe(true); + }); + + test('should have a "pause", "edit" and "unfollow" action when the follower index is active', async () => { + selectFollowerIndexAt(0); + openContextMenu(); + + const contextMenu = find('followerIndexActionContextMenu'); + + expect(contextMenu.length).toBeTruthy(); + const contextMenuButtons = contextMenu.find('button'); + const buttonsLabel = contextMenuButtons.map(btn => btn.text()); + + expect(buttonsLabel).toEqual([ + 'Pause replication', + 'Edit follower index', + 'Unfollow leader index' + ]); + }); + + test('should have a "resume", "edit" and "unfollow" action when the follower index is active', async () => { + selectFollowerIndexAt(1); // Select the second follower that is "paused" + openContextMenu(); + + const contextMenu = find('followerIndexActionContextMenu'); + + const contextMenuButtons = contextMenu.find('button'); + const buttonsLabel = contextMenuButtons.map(btn => btn.text()); + expect(buttonsLabel).toEqual([ + 'Resume replication', + 'Edit follower index', + 'Unfollow leader index' + ]); + }); + + test('should open a confirmation modal when clicking on "pause replication"', () => { + expect(exists('ccrFollowerIndexPauseReplicationConfirmationModal')).toBe(false); + + selectFollowerIndexAt(0); + openContextMenu(); + clickContextMenuButtonAt(0); // first button is the "pause" action + + expect(exists('ccrFollowerIndexPauseReplicationConfirmationModal')).toBe(true); + }); + + test('should open a confirmation modal when clicking on "unfollow leader index"', () => { + expect(exists('ccrFollowerIndexUnfollowLeaderConfirmationModal')).toBe(false); + + selectFollowerIndexAt(0); + openContextMenu(); + clickContextMenuButtonAt(2); // third button is the "unfollow" action + + expect(exists('ccrFollowerIndexUnfollowLeaderConfirmationModal')).toBe(true); + }); + }); + + describe('table row action menu', () => { + test('should open a context menu when clicking on the button of each row', async () => { + expect(component.find('.euiContextMenuPanel').length).toBe(0); + + openTableRowContextMenuAt(0); + + expect(component.find('.euiContextMenuPanel').length).toBe(1); + }); + + test('should have the "pause", "edit" and "unfollow" options in the row context menu', async () => { + openTableRowContextMenuAt(0); + + const buttonLabels = component + .find('.euiContextMenuPanel') + .find('.euiContextMenuItem') + .map(button => button.text()); + + expect(buttonLabels).toEqual([ + 'Pause replication', + 'Edit follower index', + 'Unfollow leader index' + ]); + }); + + test('should have the "resume", "edit" and "unfollow" options in the row context menu', async () => { + // We open the context menu of the second row (index 1) as followerIndices[1].status is "paused" + openTableRowContextMenuAt(1); + + const buttonLabels = component + .find('.euiContextMenuPanel') + .find('.euiContextMenuItem') + .map(button => button.text()); + + expect(buttonLabels).toEqual([ + 'Resume replication', + 'Edit follower index', + 'Unfollow leader index' + ]); + }); + + test('should open a confirmation modal when clicking on "pause replication"', async () => { + expect(exists('ccrFollowerIndexPauseReplicationConfirmationModal')).toBe(false); + + openTableRowContextMenuAt(0); + find('ccrFollowerIndexListPauseActionButton').simulate('click'); + + expect(exists('ccrFollowerIndexPauseReplicationConfirmationModal')).toBe(true); + }); + + test('should open a confirmation modal when clicking on "resume"', async () => { + expect(exists('ccrFollowerIndexResumeReplicationConfirmationModal')).toBe(false); + + openTableRowContextMenuAt(1); // open the second row context menu, as it is a "paused" follower index + find('ccrFollowerIndexListResumeActionButton').simulate('click'); + + expect(exists('ccrFollowerIndexResumeReplicationConfirmationModal')).toBe(true); + }); + + test('should open a confirmation modal when clicking on "unfollow leader index"', () => { + expect(exists('ccrFollowerIndexUnfollowLeaderConfirmationModal')).toBe(false); + + openTableRowContextMenuAt(0); + find('ccrFollowerIndexListUnfollowActionButton').simulate('click'); + + expect(exists('ccrFollowerIndexUnfollowLeaderConfirmationModal')).toBe(true); + }); + }); + + describe('detail panel', () => { + test('should open a detail panel when clicking on a follower index', () => { + expect(exists('ccrFollowerIndexDetailsFlyout')).toBe(false); + + clickFollowerIndexAt(0); + + expect(exists('ccrFollowerIndexDetailsFlyout')).toBe(true); + }); + + test('should set the title the index that has been selected', () => { + clickFollowerIndexAt(0); // Open the detail panel + expect(find('followerIndexDetailsFlyoutTitle').text()).toEqual(index1.name); + }); + + test('should have a "settings" section', () => { + clickFollowerIndexAt(0); + expect(find('ccrFollowerIndexDetailPanelSettingsSection').find('h3').text()).toEqual('Settings'); + expect(exists('ccrFollowerIndexDetailPanelSettingsValues')).toBe(true); + }); + + test('should set the correct follower index settings values', () => { + const mapSettingsToFollowerIndexProp = { + 'Status': 'status', + 'RemoteCluster': 'remoteCluster', + 'LeaderIndex': 'leaderIndex', + 'MaxReadReqOpCount': 'maxReadRequestOperationCount', + 'MaxOutstandingReadReq': 'maxOutstandingReadRequests', + 'MaxReadReqSize': 'maxReadRequestSize', + 'MaxWriteReqOpCount': 'maxWriteRequestOperationCount', + 'MaxWriteReqSize': 'maxWriteRequestSize', + 'MaxOutstandingWriteReq': 'maxOutstandingWriteRequests', + 'MaxWriteBufferCount': 'maxWriteBufferCount', + 'MaxWriteBufferSize': 'maxWriteBufferSize', + 'MaxRetryDelay': 'maxRetryDelay', + 'ReadPollTimeout': 'readPollTimeout' + }; + + clickFollowerIndexAt(0); + + Object.entries(mapSettingsToFollowerIndexProp).forEach(([setting, prop]) => { + const wrapper = find(`ccrFollowerIndexDetail${setting}`); + + if (!wrapper.length) { + throw new Error(`Could not find description for setting "${setting}"`); + } + + expect(wrapper.text()).toEqual(index1[prop].toString()); + }); + }); + + test('should not have settings values for a "paused" follower index', () => { + clickFollowerIndexAt(1); // the second follower index is paused + expect(exists('ccrFollowerIndexDetailPanelSettingsValues')).toBe(false); + expect(find('ccrFollowerIndexDetailPanelSettingsSection').text()).toContain('paused follower index does not have settings'); + }); + + test('should have a section to render the follower index shards stats', () => { + clickFollowerIndexAt(0); + expect(exists('ccrFollowerIndexDetailPanelShardsStatsSection')).toBe(true); + }); + + test('should render a EuiCodeEditor for each shards stats', () => { + clickFollowerIndexAt(0); + + const codeEditors = component.find(`EuiCodeEditor`); + + expect(codeEditors.length).toBe(index1.shards.length); + codeEditors.forEach((codeEditor, i) => { + expect(JSON.parse(codeEditor.props().value)).toEqual(index1.shards[i]); + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js new file mode 100644 index 0000000000000..5d09018a2bbd6 --- /dev/null +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js @@ -0,0 +1,84 @@ +/* + * 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 sinon from 'sinon'; + +import { initTestBed, mockAllHttpRequests, nextTick } from './test_helpers'; +import { CrossClusterReplicationHome } from '../../public/app/sections/home/home'; +import { BASE_PATH } from '../../common/constants'; +import routing from '../../public/app/services/routing'; + +jest.mock('ui/chrome', () => ({ + addBasePath: () => 'api/cross_cluster_replication', + breadcrumbs: { set: () => {} }, +})); + +jest.mock('ui/index_patterns', () => { + const { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } = require.requireActual('../../../../../src/legacy/ui/public/index_patterns/constants'); // eslint-disable-line max-len + return { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE }; +}); + +const testBedOptions = { + memoryRouter: { + initialEntries: [`${BASE_PATH}/follower_indices`], + componentRoutePath: `${BASE_PATH}/:section`, + onRouter: (router) => routing.reactRouter = router + } +}; + +describe('', () => { + let server; + let find; + let exists; + let component; + + beforeEach(() => { + server = sinon.fakeServer.create(); + server.respondImmediately = true; + mockAllHttpRequests(server); + }); + + describe('on component mount', () => { + beforeEach(async () => { + ({ exists, find, component } = initTestBed(CrossClusterReplicationHome, undefined, testBedOptions)); + }); + + test('should set the correct an app title', () => { + expect(exists('ccrAppTitle')).toBe(true); + expect(find('ccrAppTitle').text()).toEqual('Cross Cluster Replication'); + }); + + test('should have 2 tabs to switch between "Follower indices" & "Auto-follow patterns"', () => { + expect(exists('ccrFollowerIndicesTab')).toBe(true); + expect(find('ccrFollowerIndicesTab').text()).toEqual('Follower indices'); + + expect(exists('ccrAutoFollowPatternsTab')).toBe(true); + expect(find('ccrAutoFollowPatternsTab').text()).toEqual('Auto-follow patterns'); + }); + + test('should set the default selected tab to "Follower indices"', () => { + expect(component.find('.euiTab-isSelected').text()).toBe('Follower indices'); + + // Verify that the component is rendered + expect(component.find('FollowerIndicesList').length).toBe(1); + }); + }); + + describe('section change', () => { + test('should change to auto-follow pattern', async () => { + const autoFollowPatternsTab = find('ccrAutoFollowPatternsTab'); + + autoFollowPatternsTab.simulate('click'); + await nextTick(); + component.update(); + + expect(component.find('.euiTab-isSelected').text()).toBe('Auto-follow patterns'); + + // Verify that the component is rendered + expect(component.find('AutoFollowPatternList').length).toBe(1); + }); + }); +}); diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js new file mode 100644 index 0000000000000..2bd747977c111 --- /dev/null +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js @@ -0,0 +1,212 @@ +/* + * 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 axios from 'axios'; + +import { registerTestBed, findTestSubject } from '../../../../test_utils'; +import { ccrStore } from '../../public/app/store'; +import { setHttpClient } from '../../public/app/services/api'; +import routing from '../../public/app/services/routing'; + +// Mock React router +const reactRouter = { + history: { + push: () => {}, + createHref: (location) => location.pathname, + location: '' + } +}; + +routing.reactRouter = reactRouter; +// Mock Angular $q +const $q = { defer: () => ({ resolve() {} }) }; +// axios has a $http like interface so using it to simulate $http +setHttpClient(axios.create(), $q); + +const initUserActions = ({ getMetadataFromEuiTable, find }) => (section) => { + const userActions = { + // Follower indices user actions + followerIndicesList() { + const { rows } = getMetadataFromEuiTable('ccrFollowerIndexListTable'); + + const selectFollowerIndexAt = (index = 0) => { + const row = rows[index]; + const checkBox = row.reactWrapper.find('input').hostNodes(); + checkBox.simulate('change', { target: { checked: true } }); + }; + + const openContextMenu = () => { + find('ccrFollowerIndexListContextMenuButton').simulate('click'); + }; + + const clickContextMenuButtonAt = (index = 0) => { + const contextMenu = find('followerIndexActionContextMenu'); + contextMenu.find('button').at(index).simulate('click'); + }; + + const openTableRowContextMenuAt = (index = 0) => { + const actionsColumnIndex = rows[0].columns.length - 1; // Actions are in the last column + const actionsTableCell = rows[index].columns[actionsColumnIndex]; + const button = actionsTableCell.reactWrapper.find('button'); + if (!button.length) { + throw new Error(`No button to open context menu were found on Follower index list table row ${index}`); + } + button.simulate('click'); + }; + + const clickFollowerIndexAt = (index = 0) => { + const followerIndexLink = findTestSubject(rows[index].reactWrapper, 'ccrFollowerIndexListFollowerIndexLink'); + followerIndexLink.simulate('click'); + }; + + return { + selectFollowerIndexAt, + openContextMenu, + clickContextMenuButtonAt, + openTableRowContextMenuAt, + clickFollowerIndexAt, + }; + }, + // Auto-follow patterns user actions + autoFollowPatternList() { + const { rows } = getMetadataFromEuiTable('ccrAutoFollowPatternListTable'); + + const selectAutoFollowPatternAt = (index = 0) => { + const row = rows[index]; + const checkBox = row.reactWrapper.find('input').hostNodes(); + checkBox.simulate('change', { target: { checked: true } }); + }; + + const clickBulkDeleteButton = () => { + find('ccrAutoFollowPatternListBulkDeleteActionButton').simulate('click'); + }; + + const clickConfirmModalDeleteAutoFollowPattern = () => { + const modal = find('ccrAutoFollowPatternDeleteConfirmationModal'); + findTestSubject(modal, 'confirmModalConfirmButton').simulate('click'); + }; + + const clickRowActionButtonAt = (index = 0, action = 'delete') => { + const indexLastColumn = rows[index].columns.length - 1; + const tableCellActions = rows[index].columns[indexLastColumn].reactWrapper; + + let button; + if (action === 'delete') { + button = findTestSubject(tableCellActions, 'ccrAutoFollowPatternListDeleteActionButton'); + } else if (action === 'edit') { + findTestSubject(tableCellActions, 'ccrAutoFollowPatternListEditActionButton'); + } + + if (!button) { + throw new Error(`Button for action "${action}" not found.`); + } + + button.simulate('click'); + }; + + const clickAutoFollowPatternAt = (index = 0) => { + const autoFollowPatternLink = findTestSubject(rows[index].reactWrapper, 'ccrAutoFollowPatternListPatternLink'); + autoFollowPatternLink.simulate('click'); + }; + + return { + selectAutoFollowPatternAt, + clickBulkDeleteButton, + clickConfirmModalDeleteAutoFollowPattern, + clickRowActionButtonAt, + clickAutoFollowPatternAt + }; + } + }; + + return userActions[section](); +}; + +export { nextTick, getRandomString, findTestSubject } from '../../../../test_utils'; + +export const initTestBed = (component, props = {}, options) => { + const testBed = registerTestBed(component, {}, ccrStore)(props, options); + const getUserActions = initUserActions(testBed); + + return { + ...testBed, + getUserActions, + }; +}; + +export const mockAllHttpRequests = server => { + const mockResponse = (defaultResponse, response) => ([ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({ ...defaultResponse, ...response }), + ]); + + const setLoadFollowerIndicesResponse = (response) => { + const defaultResponse = { indices: [] }; + + server.respondWith('GET', 'api/cross_cluster_replication/follower_indices', + mockResponse(defaultResponse, response)); + }; + + const setLoadAutoFollowPatternsResponse = (response) => { + const defaultResponse = { patterns: [] }; + + server.respondWith('GET', 'api/cross_cluster_replication/auto_follow_patterns', + mockResponse(defaultResponse, response) + ); + }; + + const setDeleteAutoFollowPatternResponse = (response) => { + const defaultResponse = { errors: [], itemsDeleted: [] }; + + server.respondWith('DELETE', /api\/cross_cluster_replication\/auto_follow_patterns/, + mockResponse(defaultResponse, response) + ); + }; + + const setAutoFollowStatsResponse = (response) => { + const defaultResponse = { + numberOfFailedFollowIndices: 0, + numberOfFailedRemoteClusterStateRequests: 0, + numberOfSuccessfulFollowIndices: 0, + recentAutoFollowErrors: [], + autoFollowedClusters: [{ + clusterName: 'new-york', + timeSinceLastCheckMillis: 13746, + lastSeenMetadataVersion: 22 + }] + }; + + server.respondWith('GET', 'api/cross_cluster_replication/stats/auto_follow', + mockResponse(defaultResponse, response) + ); + }; + + /** + * Set all http request to their default response + */ + setLoadFollowerIndicesResponse(); + setLoadAutoFollowPatternsResponse(); + setAutoFollowStatsResponse(); + + /** + * Return a method to override any of the http reques + */ + return (request, response) => { + const mapRequestToHelper = { + 'loadFollowerIndices': setLoadFollowerIndicesResponse, + 'loadAutoFollowPatterns': setLoadAutoFollowPatternsResponse, + 'deleteAutoFollowPattern': setDeleteAutoFollowPatternResponse, + 'autoFollowStats': setAutoFollowStatsResponse, + }; + + if (!mapRequestToHelper[request]) { + throw new Error(`Did not find a helper to set http response for request ${request}`); + } + + return mapRequestToHelper[request](response); + }; +}; diff --git a/x-pack/plugins/cross_cluster_replication/fixtures/auto_follow_pattern.js b/x-pack/plugins/cross_cluster_replication/fixtures/auto_follow_pattern.js index 187b91b66ea73..cfedad5c1c072 100644 --- a/x-pack/plugins/cross_cluster_replication/fixtures/auto_follow_pattern.js +++ b/x-pack/plugins/cross_cluster_replication/fixtures/auto_follow_pattern.js @@ -4,14 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -const Chance = require('chance'); // eslint-disable-line import/no-extraneous-dependencies -const chance = new Chance(); +import { getRandomString } from '../../../test_utils'; export const getAutoFollowPatternMock = ( - name = chance.string(), - remoteCluster = chance.string(), - leaderIndexPatterns = [chance.string()], - followIndexPattern = chance.string() + name = getRandomString(), + remoteCluster = getRandomString(), + leaderIndexPatterns = [getRandomString()], + followIndexPattern = getRandomString() ) => ({ name, pattern: { @@ -33,3 +32,18 @@ export const getAutoFollowPatternListMock = (total = 3) => { return list; }; + +// ----------------- +// Client test mock +// ----------------- +export const getAutoFollowPatternClientMock = ({ + name = getRandomString(), + remoteCluster = getRandomString(), + leaderIndexPatterns = [`${getRandomString()}-*`], + followIndexPattern = getRandomString() +}) => ({ + name, + remoteCluster, + leaderIndexPatterns, + followIndexPattern, +}); diff --git a/x-pack/plugins/cross_cluster_replication/fixtures/follower_index.js b/x-pack/plugins/cross_cluster_replication/fixtures/follower_index.js index ef888f8929a26..e873c1a394f44 100644 --- a/x-pack/plugins/cross_cluster_replication/fixtures/follower_index.js +++ b/x-pack/plugins/cross_cluster_replication/fixtures/follower_index.js @@ -6,6 +6,63 @@ const Chance = require('chance'); // eslint-disable-line import/no-extraneous-dependencies const chance = new Chance(); +import { getRandomString } from '../../../test_utils'; + +const serializeShard = ({ + id, + remoteCluster, + leaderIndex, + leaderGlobalCheckpoint, + leaderMaxSequenceNum, + followerGlobalCheckpoint, + followerMaxSequenceNum, + lastRequestedSequenceNum, + outstandingReadRequestsCount, + outstandingWriteRequestsCount, + writeBufferOperationsCount, + writeBufferSizeBytes, + followerMappingVersion, + followerSettingsVersion, + totalReadTimeMs, + totalReadRemoteExecTimeMs, + successfulReadRequestCount, + failedReadRequestsCount, + operationsReadCount, + bytesReadCount, + totalWriteTimeMs, + successfulWriteRequestsCount, + failedWriteRequestsCount, + operationsWrittenCount, + readExceptions, + timeSinceLastReadMs, +}) => ({ + shard_id: id, + remote_cluster: remoteCluster, + leader_index: leaderIndex, + leader_global_checkpoint: leaderGlobalCheckpoint, + leader_max_seq_no: leaderMaxSequenceNum, + follower_global_checkpoint: followerGlobalCheckpoint, + follower_max_seq_no: followerMaxSequenceNum, + last_requested_seq_no: lastRequestedSequenceNum, + outstanding_read_requests: outstandingReadRequestsCount, + outstanding_write_requests: outstandingWriteRequestsCount, + write_buffer_operation_count: writeBufferOperationsCount, + write_buffer_size_in_bytes: writeBufferSizeBytes, + follower_mapping_version: followerMappingVersion, + follower_settings_version: followerSettingsVersion, + total_read_time_millis: totalReadTimeMs, + total_read_remote_exec_time_millis: totalReadRemoteExecTimeMs, + successful_read_requests: successfulReadRequestCount, + failed_read_requests: failedReadRequestsCount, + operations_read: operationsReadCount, + bytes_read: bytesReadCount, + total_write_time_millis: totalWriteTimeMs, + successful_write_requests: successfulWriteRequestsCount, + failed_write_requests: failedWriteRequestsCount, + operations_written: operationsWrittenCount, + read_exceptions: readExceptions, + time_since_last_read_millis: timeSinceLastReadMs, +}); export const getFollowerIndexStatsMock = ( name = chance.string(), @@ -37,68 +94,10 @@ export const getFollowerIndexStatsMock = ( readExceptions: [ chance.string() ], timeSinceLastReadMs: chance.integer(), }] -) => { - const serializeShard = ({ - id, - remoteCluster, - leaderIndex, - leaderGlobalCheckpoint, - leaderMaxSequenceNum, - followerGlobalCheckpoint, - followerMaxSequenceNum, - lastRequestedSequenceNum, - outstandingReadRequestsCount, - outstandingWriteRequestsCount, - writeBufferOperationsCount, - writeBufferSizeBytes, - followerMappingVersion, - followerSettingsVersion, - totalReadTimeMs, - totalReadRemoteExecTimeMs, - successfulReadRequestCount, - failedReadRequestsCount, - operationsReadCount, - bytesReadCount, - totalWriteTimeMs, - successfulWriteRequestsCount, - failedWriteRequestsCount, - operationsWrittenCount, - readExceptions, - timeSinceLastReadMs, - }) => ({ - shard_id: id, - remote_cluster: remoteCluster, - leader_index: leaderIndex, - leader_global_checkpoint: leaderGlobalCheckpoint, - leader_max_seq_no: leaderMaxSequenceNum, - follower_global_checkpoint: followerGlobalCheckpoint, - follower_max_seq_no: followerMaxSequenceNum, - last_requested_seq_no: lastRequestedSequenceNum, - outstanding_read_requests: outstandingReadRequestsCount, - outstanding_write_requests: outstandingWriteRequestsCount, - write_buffer_operation_count: writeBufferOperationsCount, - write_buffer_size_in_bytes: writeBufferSizeBytes, - follower_mapping_version: followerMappingVersion, - follower_settings_version: followerSettingsVersion, - total_read_time_millis: totalReadTimeMs, - total_read_remote_exec_time_millis: totalReadRemoteExecTimeMs, - successful_read_requests: successfulReadRequestCount, - failed_read_requests: failedReadRequestsCount, - operations_read: operationsReadCount, - bytes_read: bytesReadCount, - total_write_time_millis: totalWriteTimeMs, - successful_write_requests: successfulWriteRequestsCount, - failed_write_requests: failedWriteRequestsCount, - operations_written: operationsWrittenCount, - read_exceptions: readExceptions, - time_since_last_read_millis: timeSinceLastReadMs, - }); - - return { - index: name, - shards: shards.map(serializeShard), - }; -}; +) => ({ + index: name, + shards: shards.map(serializeShard), +}); export const getFollowerIndexListStatsMock = (total = 3, names) => { const list = { @@ -157,3 +156,57 @@ export const getFollowerIndexListInfoMock = (total = 3) => { return list; }; + +// ----------------- +// Client test mock +// ----------------- + +export const getFollowerIndexMock = ({ + name = getRandomString(), + remoteCluster = getRandomString(), + leaderIndex = getRandomString(), + status = 'Active' +} = {}) => ({ + name, + remoteCluster, + leaderIndex, + status, + maxReadRequestOperationCount: chance.integer(), + maxOutstandingReadRequests: chance.integer(), + maxReadRequestSize: getRandomString({ length: 5 }), + maxWriteRequestOperationCount: chance.integer(), + maxWriteRequestSize: '9223372036854775807b', + maxOutstandingWriteRequests: chance.integer(), + maxWriteBufferCount: chance.integer(), + maxWriteBufferSize: getRandomString({ length: 5 }), + maxRetryDelay: getRandomString({ length: 5 }), + readPollTimeout: getRandomString({ length: 5 }), + shards: [{ + id: 0, + remoteCluster: remoteCluster, + leaderIndex: leaderIndex, + leaderGlobalCheckpoint: chance.integer(), + leaderMaxSequenceNum: chance.integer(), + followerGlobalCheckpoint: chance.integer(), + followerMaxSequenceNum: chance.integer(), + lastRequestedSequenceNum: chance.integer(), + outstandingReadRequestsCount: chance.integer(), + outstandingWriteRequestsCount: chance.integer(), + writeBufferOperationsCount: chance.integer(), + writeBufferSizeBytes: chance.integer(), + followerMappingVersion: chance.integer(), + followerSettingsVersion: chance.integer(), + totalReadTimeMs: chance.integer(), + totalReadRemoteExecTimeMs: chance.integer(), + successfulReadRequestCount: chance.integer(), + failedReadRequestsCount: chance.integer(), + operationsReadCount: chance.integer(), + bytesReadCount: chance.integer(), + totalWriteTimeMs: chance.integer(), + successfulWriteRequestsCount: chance.integer(), + failedWriteRequestsCount: chance.integer(), + operationsWrittenCount: chance.integer(), + readExceptions: [], + timeSinceLastReadMs: chance.integer(), + }] +}); diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.js b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.js index e48347a171127..9c617446b28a2 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.js @@ -87,6 +87,7 @@ class AutoFollowPatternDeleteProviderUi extends PureComponent { ) } onMouseOver={this.onMouseOverModal} + data-test-subj="ccrAutoFollowPatternDeleteConfirmationModal" > {!isSingle && ( diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.js b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.js index 3e41cb9bdcefd..c76c13c44d51f 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.js @@ -36,7 +36,7 @@ export const AutoFollowPatternIndicesPreview = ({ prefix, suffix, leaderIndexPat />
    {indicesPreview.map(({ followPattern: { prefix, suffix, template } }, i) => ( -
  • +
  • {prefix}{template}{suffix}
  • ))} diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_pause_provider.js b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_pause_provider.js index 3beb0353b4e38..77a887c9792e5 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_pause_provider.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_pause_provider.js @@ -81,6 +81,7 @@ class FollowerIndexPauseProviderUi extends PureComponent { defaultMessage: 'Pause replication', })} onMouseOver={this.onMouseOverModal} + data-test-subj="ccrFollowerIndexPauseReplicationConfirmationModal" > {hasCustomSettings && (

    diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js index fd9a530f752df..0570040bd3661 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_resume_provider.js @@ -94,6 +94,7 @@ class FollowerIndexResumeProviderUi extends PureComponent { ) } onMouseOver={this.onMouseOverModal} + data-test-subj="ccrFollowerIndexResumeReplicationConfirmationModal" > {isSingle ? (

    diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_unfollow_provider.js b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_unfollow_provider.js index 07d69cee659c8..d509db1247f4f 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_unfollow_provider.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/follower_index_unfollow_provider.js @@ -92,6 +92,7 @@ class FollowerIndexUnfollowProviderUi extends PureComponent { ) } onMouseOver={this.onMouseOverModal} + data-test-subj="ccrFollowerIndexUnfollowLeaderConfirmationModal" > {isSingle ? ( diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/section_error.js b/x-pack/plugins/cross_cluster_replication/public/app/components/section_error.js index 4e4abfa571c70..4988449802b53 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/section_error.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/section_error.js @@ -11,11 +11,12 @@ import { } from '@elastic/eui'; export function SectionError({ title, error }) { + const data = error.data ? error.data : error; const { error: errorString, cause, // wrapEsError() on the server add a "cause" array message, - } = error.data; + } = data; return ( diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.js index 22b1a47ca929a..b3551998070b8 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.js @@ -135,7 +135,7 @@ export class AutoFollowPatternList extends PureComponent { } renderContent(isEmpty) { - const { apiError, isAuthorized } = this.props; + const { apiError, apiStatus, isAuthorized } = this.props; if (!isAuthorized) { return ( @@ -172,6 +172,17 @@ export class AutoFollowPatternList extends PureComponent { return this.renderEmpty(); } + if (apiStatus === API_STATUS.LOADING) { + return ( + + + + ); + } + return this.renderList(); } @@ -211,6 +222,7 @@ export class AutoFollowPatternList extends PureComponent { /> } + data-test-subj="ccrAutoFollowPatternEmptyPrompt" /> ); } @@ -219,22 +231,10 @@ export class AutoFollowPatternList extends PureComponent { const { selectAutoFollowPattern, autoFollowPatterns, - apiStatus, } = this.props; const { isDetailPanelOpen } = this.state; - if (apiStatus === API_STATUS.LOADING) { - return ( - - - - ); - } - return ( diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/auto_follow_pattern_table.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/auto_follow_pattern_table.js index f86b184c66bc9..a5b46ff3e17f0 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/auto_follow_pattern_table.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/auto_follow_pattern_table/auto_follow_pattern_table.js @@ -261,6 +261,7 @@ export class AutoFollowPatternTable extends PureComponent { cellProps={(item, column) => ({ 'data-test-subj': `ccrAutoFollowPatternListTableCell-${column.field}` })} + data-test-subj="ccrAutoFollowPatternListTable" /> {this.renderLoading()} diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js index 2cfe54b2a0e06..ef014c75447ff 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js @@ -4,12 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; import { getIndexListUri } from '../../../../../../../../index_management/public/services/navigation'; - import { EuiButton, EuiButtonEmpty, @@ -24,7 +23,6 @@ import { EuiFlyoutHeader, EuiIcon, EuiLink, - EuiLoadingSpinner, EuiSpacer, EuiText, EuiTextColor, @@ -36,7 +34,6 @@ import { AutoFollowPatternDeleteProvider, } from '../../../../../components'; -import { API_STATUS } from '../../../../../constants'; import routing from '../../../../../services/routing'; export class DetailPanel extends Component { @@ -47,155 +44,154 @@ export class DetailPanel extends Component { closeDetailPanel: PropTypes.func.isRequired, } - renderAutoFollowPattern() { - const { - autoFollowPattern: { - followIndexPatternPrefix, - followIndexPatternSuffix, - remoteCluster, - leaderIndexPatterns, - }, - } = this.props; - - let indexManagementFilter; - if(followIndexPatternPrefix) { - indexManagementFilter = `name:${followIndexPatternPrefix}`; - } else if(followIndexPatternSuffix) { - indexManagementFilter = `name:${followIndexPatternSuffix}`; - } - const indexManagementUri = getIndexListUri(indexManagementFilter); - + renderAutoFollowPattern({ followIndexPatternPrefix, followIndexPatternSuffix, remoteCluster, leaderIndexPatterns }) { return ( - - - -

    - -

    - +
    + +

    + +

    +
    - + - - - - - - - - + + + + + + + + - - {remoteCluster} - - + + {remoteCluster} + + - - - - - - + + + + + + - - {leaderIndexPatterns.join(', ')} - - - + + {leaderIndexPatterns.join(', ')} + + + - + + + + + + + + + - - - - + + {followIndexPatternPrefix || ( + - - - - - {followIndexPatternPrefix || ( - - - - )} - - - - - - + + )} + + + + + + + + + + + + {followIndexPatternSuffix || ( + - - - - - {followIndexPatternSuffix || ( - - - - )} - - - - - - - - - + + )} + + + + +
    + ); + } - - - - - - {this.renderAutoFollowPatternErrors()} - - + renderIndicesPreview(prefix, suffix, leaderIndexPatterns) { + return ( +
    + +
    ); } - renderAutoFollowPatternErrors() { - const { autoFollowPattern } = this.props; + renderAutoFollowPatternNotFound() { + return ( + + + + + + + + + + + + + + + + ); + } + renderAutoFollowPatternErrors(autoFollowPattern) { if (!autoFollowPattern.errors.length) { return null; } return ( - +
    - +

      {autoFollowPattern.errors.map((error, i) => ( -
    • {error.autoFollowException.reason}
    • +
    • + {error.autoFollowException.reason} +
    • ))}
    - +

    ); } - renderContent() { + renderFlyoutBody() { + const { autoFollowPattern } = this.props; + + if (!autoFollowPattern) { + return this.renderAutoFollowPatternNotFound(); + } + const { - apiStatus, - autoFollowPattern, - } = this.props; + followIndexPatternPrefix, + followIndexPatternSuffix, + leaderIndexPatterns, + } = autoFollowPattern; - if (apiStatus === API_STATUS.LOADING) { - return ( - - - - - + let indexManagementFilter; - - - - - - - - - - ); + if(followIndexPatternPrefix) { + indexManagementFilter = `name:${followIndexPatternPrefix}`; + } else if(followIndexPatternSuffix) { + indexManagementFilter = `name:${followIndexPatternSuffix}`; } - if (!autoFollowPattern) { - return ( - - - - - + const indexManagementUri = getIndexListUri(indexManagementFilter); - - - - - - - - - - ); - } + return ( + + {this.renderAutoFollowPattern(autoFollowPattern)} + + - return this.renderAutoFollowPattern(); + {this.renderIndicesPreview(followIndexPatternPrefix, followIndexPatternSuffix, leaderIndexPatterns)} + + + + + + + + + + {this.renderAutoFollowPatternErrors(autoFollowPattern)} + + + ); } - renderFooter() { + renderFlyoutFooter() { const { autoFollowPattern, closeDetailPanel, @@ -306,7 +295,6 @@ export class DetailPanel extends Component { flush="left" onClick={closeDetailPanel} data-test-subj="ccrAutoFollowPatternDetailsFlyoutCloseButton" - > - +

    {autoFollowPatternId}

    - {this.renderContent()} - {this.renderFooter()} + {this.renderFlyoutBody()} + {this.renderFlyoutFooter()} ); } diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.js index c58595898c0a5..10008e7a68fc9 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/context_menu/context_menu.js @@ -103,7 +103,7 @@ export class ContextMenu extends PureComponent { values={{ followerIndicesLength }} /> - + { activeFollowerIndices.length ? ( diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js index a9520f67cec58..2dac2bfc51403 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js @@ -69,99 +69,104 @@ export class DetailPanel extends Component { return ( - -

    - -

    -
    +
    + + + + + + + + - + + {isPaused ? ( + + + + ) : ( + + + + )} + + + - - - - - - - - + - - {isPaused ? ( - + + + + - - ) : ( - + + + + + {remoteCluster} + + + + + + - - )} - - - + + - - - - - - - - - + + {leaderIndex} + + + + +
    - - {remoteCluster} - - + - - - - - - +
    + +

    + +

    +
    - - {leaderIndex} - - - + {isPaused ? ( - - - - } - /> - + + } + /> ) : ( - - + @@ -173,7 +178,7 @@ export class DetailPanel extends Component { - + {maxReadRequestOperationCount} @@ -188,7 +193,7 @@ export class DetailPanel extends Component { - + {maxOutstandingReadRequests} @@ -207,7 +212,7 @@ export class DetailPanel extends Component { - + {maxReadRequestSize} @@ -222,7 +227,7 @@ export class DetailPanel extends Component { - + {maxWriteRequestOperationCount} @@ -241,7 +246,7 @@ export class DetailPanel extends Component { - + {maxWriteRequestSize} @@ -256,7 +261,7 @@ export class DetailPanel extends Component { - + {maxOutstandingWriteRequests} @@ -275,7 +280,7 @@ export class DetailPanel extends Component { - + {maxWriteBufferCount} @@ -290,7 +295,7 @@ export class DetailPanel extends Component { - + {maxWriteBufferSize} @@ -309,7 +314,7 @@ export class DetailPanel extends Component { - + {maxRetryDelay} @@ -324,16 +329,18 @@ export class DetailPanel extends Component { - + {readPollTimeout} - + )} +
    - + +
    {shards && shards.map((shard, i) => ( @@ -359,10 +366,11 @@ export class DetailPanel extends Component { editorProps={{ $blockScrolling: Infinity }} + data-test-subj={`ccrFollowerIndexDetailPanelShardsStats${i}`} /> ))} - +
    ); @@ -510,7 +518,11 @@ export class DetailPanel extends Component { > - +

    {followerIndexId}

    diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.js index 0b387ad097e0e..0f663bc71313a 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/follower_indices_table/follower_indices_table.js @@ -93,7 +93,7 @@ export class FollowerIndicesTable extends PureComponent { {(resumeFollowerIndex) => ( resumeFollowerIndex(name)} - data-test-subj="ccrFollowerIndexListPauseActionButton" + data-test-subj="ccrFollowerIndexListResumeActionButton" > ( pauseFollowerIndex(followerIndex)} - data-test-subj="ccrFollowerIndexListResumeActionButton" + data-test-subj="ccrFollowerIndexListPauseActionButton" > ({ 'data-test-subj': `ccrFollowerIndexListTableCell-${column.field}` })} + data-test-subj="ccrFollowerIndexListTable" /> {this.renderLoading()}
    diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.js index 0990e814a7189..16f6e89ec054d 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/follower_indices_list.js @@ -131,7 +131,7 @@ export class FollowerIndicesList extends PureComponent { } renderContent(isEmpty) { - const { apiError, isAuthorized } = this.props; + const { apiError, isAuthorized, apiStatus } = this.props; if (!isAuthorized) { return ( @@ -168,6 +168,10 @@ export class FollowerIndicesList extends PureComponent { return this.renderEmpty(); } + if (apiStatus === API_STATUS.LOADING) { + return this.renderLoading(); + } + return this.renderList(); } @@ -206,30 +210,30 @@ export class FollowerIndicesList extends PureComponent { /> } + data-test-subj="ccrFollowerIndexEmptyPrompt" /> ); } + renderLoading() { + return ( + + + + ); + } + renderList() { const { selectFollowerIndex, followerIndices, - apiStatus, } = this.props; const { isDetailPanelOpen } = this.state; - if (apiStatus === API_STATUS.LOADING) { - return ( - - - - ); - } - return ( diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js index 0252616ce4cd5..b9e7f68e77614 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js @@ -69,7 +69,7 @@ export class CrossClusterReplicationHome extends PureComponent { return ( - +

    this.onSectionChange(tab.id)} isSelected={tab.id === this.state.activeSection} key={tab.id} - data-test-subject={tab.testSubj} + data-test-subj={tab.testSubj} > {tab.name} diff --git a/x-pack/plugins/rollup/__jest__/client_integration/job_create.test_helpers.js b/x-pack/plugins/rollup/__jest__/client_integration/job_create.test_helpers.js index 5cabb57f1568d..01b0464aa0e00 100644 --- a/x-pack/plugins/rollup/__jest__/client_integration/job_create.test_helpers.js +++ b/x-pack/plugins/rollup/__jest__/client_integration/job_create.test_helpers.js @@ -103,7 +103,7 @@ export const initTestBed = () => { }; }; -export const nextTick = async () => new Promise((resolve) => setTimeout(resolve)); +export { nextTick } from '../../../../test_utils'; export const mockServerResponses = server => { const mockIndexPatternValidityResponse = (response) => { diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js index 5aa47b47998bc..8b220027a75fb 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js @@ -53,24 +53,6 @@ describe('', () => { expect(component.find('JobTableUi').length).toBeTruthy(); }); - describe('route query params change', () => { - it('should call the "openDetailPanel()" prop each time the "job" query params changes', () => { - const openDetailPanel = jest.fn(); - const jobId = 'foo'; - const { setProps } = initTestBed({ openDetailPanel }); - - expect(openDetailPanel.mock.calls.length).toBe(0); - - setProps({ - history: { location: { search: `?job=${jobId}` } }, - openDetailPanel, - }); - - expect(openDetailPanel.mock.calls.length).toBe(1); - expect(openDetailPanel.mock.calls[0][0]).toEqual(jobId); - }); - }); - describe('when there is an API error', () => { const { exists, find } = initTestBed({ jobLoadError: { diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index fc13958a38912..2e521829aaf8b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3650,7 +3650,6 @@ "xpack.crossClusterReplication.autoFollowPatternDetailPanel.deleteButtonLabel": "删除", "xpack.crossClusterReplication.autoFollowPatternDetailPanel.editButtonLabel": "编辑", "xpack.crossClusterReplication.autoFollowPatternDetailPanel.leaderPatternsLabel": "Leader 模式", - "xpack.crossClusterReplication.autoFollowPatternDetailPanel.loadingLabel": "正在加载自动跟随模式……", "xpack.crossClusterReplication.autoFollowPatternDetailPanel.notFoundLabel": "未找到自动跟随模式", "xpack.crossClusterReplication.autoFollowPatternDetailPanel.prefixEmptyValue": "无前缀", "xpack.crossClusterReplication.autoFollowPatternDetailPanel.prefixLabel": "前缀", diff --git a/x-pack/test_utils/index.js b/x-pack/test_utils/index.js index 47e0c732ab135..7eca11c3f559b 100644 --- a/x-pack/test_utils/index.js +++ b/x-pack/test_utils/index.js @@ -5,4 +5,5 @@ */ export { registerTestBed } from './testbed'; -export { getRandomString } from './lib'; +export { getRandomString, nextTick } from './lib'; +export { findTestSubject } from '@elastic/eui/lib/test'; diff --git a/x-pack/test_utils/lib/index.js b/x-pack/test_utils/lib/index.js index e78e377157355..49c8ada6806b0 100644 --- a/x-pack/test_utils/lib/index.js +++ b/x-pack/test_utils/lib/index.js @@ -6,3 +6,4 @@ export { getRandomString } from './strings'; +export { nextTick } from './utils'; diff --git a/x-pack/test_utils/lib/strings.js b/x-pack/test_utils/lib/strings.js index 1c88ecf1a636a..f4ea808062edf 100644 --- a/x-pack/test_utils/lib/strings.js +++ b/x-pack/test_utils/lib/strings.js @@ -9,4 +9,4 @@ import Chance from 'chance'; const chance = new Chance(); const CHARS_POOL = 'abcdefghijklmnopqrstuvwxyz'; -export const getRandomString = () => `${chance.string({ pool: CHARS_POOL })}-${Date.now()}`; +export const getRandomString = (options = {}) => `${chance.string({ pool: CHARS_POOL, ...options })}-${Date.now()}`; diff --git a/x-pack/test_utils/lib/utils.js b/x-pack/test_utils/lib/utils.js new file mode 100644 index 0000000000000..85ab84d96cba3 --- /dev/null +++ b/x-pack/test_utils/lib/utils.js @@ -0,0 +1,8 @@ +/* + * 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. + */ + + +export const nextTick = (time = 0) => new Promise((resolve) => setTimeout(resolve, time)); diff --git a/x-pack/test_utils/testbed/testbed.js b/x-pack/test_utils/testbed/testbed.js index 03477d46ab465..30bd82c710d87 100644 --- a/x-pack/test_utils/testbed/testbed.js +++ b/x-pack/test_utils/testbed/testbed.js @@ -4,20 +4,75 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { Component } from 'react'; +import { MemoryRouter, Route } from 'react-router-dom'; +import PropTypes from 'prop-types'; import { Provider } from 'react-redux'; import { mountWithIntl } from '../enzyme_helpers'; -import { findTestSubject as findTestSubjectHelper } from '@elastic/eui/lib/test'; +import { findTestSubject as findTestSubjectHelper } from '../index'; const registerTestSubjExists = component => (testSubject, count = 1) => findTestSubjectHelper(component, testSubject).length === count; -export const registerTestBed = (Component, defaultProps, store = {}) => (props) => { +const defaultOptions = { + memoryRouter: { + wrapRoute: true, + }, +}; + +const withRoute = (WrappedComponent, componentRoutePath = '/', onRouter = () => {}) => { + return class extends Component { + static contextTypes = { + router: PropTypes.object + }; + + componentDidMount() { + const { router } = this.context; + onRouter(router); + } + + render() { + return ( + } + /> + ); + } + }; +}; + + +/** + * Register a testBed for a React component to be tested inside a Redux provider + * + * @param {React.SFC} Component A react component to test + * @param {object} defaultProps Props to initialize the component with + * @param {object} store The Redux store to initialize the Redux Provider with + * + * @returns {object} with the following properties: + * + * - component The component wrapped by the Redux provider + * - exists() Method to check if a test subject exists in the mounted component + * - find() Method to find a test subject in the mounted componenet + * - setProp() Method to update the props on the wrapped component + * - getFormErrorsMessages() Method that will find all the "".euiFormErrorText" from eui and return their text + * - getMetadataFromEuiTable() Method that will extract the table rows and column + their values from an Eui tablle component + * - form.setInput() Method to update a form input value + * - form.selectCheckBox() Method to select a form checkbox + */ +export const registerTestBed = (Component, defaultProps, store = {}) => (props, options = defaultOptions) => { + const Comp = options.memoryRouter.wrapRoute === false + ? Component + : withRoute(Component, options.memoryRouter.componentRoutePath, options.memoryRouter.onRouter); + const component = mountWithIntl( - + + + ); @@ -63,7 +118,13 @@ export const registerTestBed = (Component, defaultProps, store = {}) => (props) * @param {ReactWrapper} table enzyme react wrapper of the EuiBasicTable */ const getMetadataFromEuiTable = (tableTestSubject) => { - const rows = find(tableTestSubject) + const table = find(tableTestSubject); + + if (!table.length) { + throw new Error(`Eui Table "${tableTestSubject}" not found.`); + } + + const rows = table .find('tr') .slice(1) // we remove the first row as it is the table header .map(row => ({ From 961f7919d312dfe43b25c15d2f22a8a2e8e6a74f Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Tue, 26 Mar 2019 12:05:39 +0100 Subject: [PATCH 31/96] Force user to re-authenticate if token refresh fails with `400` status code. (#33774) --- .../security/server/lib/__tests__/errors.js | 46 ---------- .../authentication/__tests__/authenticator.js | 32 ++++++- .../authentication_result.test.ts | 92 +++++++++++++++++++ .../authentication/authentication_result.ts | 15 +++ .../lib/authentication/authenticator.js | 27 +++--- .../providers/__tests__/token.js | 53 +++++++++++ .../lib/authentication/providers/token.js | 29 +++++- x-pack/plugins/security/server/lib/errors.js | 11 --- .../security/server/lib/errors.test.ts | 68 ++++++++++++++ x-pack/plugins/security/server/lib/errors.ts | 19 ++++ 10 files changed, 313 insertions(+), 79 deletions(-) delete mode 100644 x-pack/plugins/security/server/lib/__tests__/errors.js delete mode 100644 x-pack/plugins/security/server/lib/errors.js create mode 100644 x-pack/plugins/security/server/lib/errors.test.ts create mode 100644 x-pack/plugins/security/server/lib/errors.ts diff --git a/x-pack/plugins/security/server/lib/__tests__/errors.js b/x-pack/plugins/security/server/lib/__tests__/errors.js deleted file mode 100644 index 2cf7b6957a2ba..0000000000000 --- a/x-pack/plugins/security/server/lib/__tests__/errors.js +++ /dev/null @@ -1,46 +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 expect from '@kbn/expect'; - -import * as errors from '../errors'; - -describe('lib/errors', function () { - describe('#wrapError', () => { - it('returns given object', () => { - const err = new Error(); - const returned = errors.wrapError(err); - expect(returned).to.equal(err); - }); - it('error becomes boom error', () => { - const err = new Error(); - errors.wrapError(err); - expect(err.isBoom).to.equal(true); - }); - it('defaults output.statusCode to 500', () => { - const err = new Error(); - errors.wrapError(err); - expect(err.output.statusCode).to.equal(500); - }); - it('sets output.statusCode to .status if given', () => { - const err = new Error(); - err.status = 400; - errors.wrapError(err); - expect(err.output.statusCode).to.equal(400); - }); - it('defaults message to "Internal Server Error"', () => { - const err = new Error(); - errors.wrapError(err); - expect(err.message).to.equal('Internal Server Error'); - }); - it('sets custom message if a 400 level error', () => { - const err = new Error('wat'); - err.status = 499; - errors.wrapError(err); - expect(err.output.payload.message).to.equal('wat'); - }); - }); -}); diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js index 44916c6a7bb82..cf391b4bfdfc0 100644 --- a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js +++ b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js @@ -28,11 +28,10 @@ describe('Authenticator', () => { session = sinon.createStubInstance(Session); config = { get: sinon.stub() }; - cluster = { callWithRequest: sinon.stub() }; // Cluster is returned by `getClient` function that is wrapped into `once` making cluster // a static singleton, so we should use sandbox to set/reset its behavior between tests. - cluster = sinon.stub({ callWithRequest() {} }); + cluster = sinon.stub({ callWithRequest() {}, callWithInternalUser() {} }); sandbox.stub(ClientShield, 'getClient').returns(cluster); server.config.returns(config); @@ -357,6 +356,35 @@ describe('Authenticator', () => { sinon.assert.calledWithExactly(session.clear, notSystemAPIRequest); }); + it('clears session if provider requested it via setting state to `null`.', async () => { + // Use `token` provider for this test as it's the only one that does what we want. + config.get.withArgs('xpack.security.authProviders').returns(['token']); + await initAuthenticator(server); + authenticate = server.expose.withArgs('authenticate').lastCall.args[1]; + + const request = requestFixture({ headers: { xCustomHeader: 'xxx' } }); + + session.get.withArgs(request).resolves({ + state: { accessToken: 'access-xxx', refreshToken: 'refresh-xxx' }, + provider: 'token' + }); + + session.clear.resolves(); + + cluster.callWithRequest + .withArgs(request).rejects({ body: { error: { reason: 'token expired' } } }); + + cluster.callWithInternalUser.withArgs('shield.getAccessToken').rejects( + Boom.badRequest('refresh token expired') + ); + + const authenticationResult = await authenticate(request); + expect(authenticationResult.redirected()).to.be(true); + + sinon.assert.calledOnce(session.clear); + sinon.assert.calledWithExactly(session.clear, request); + }); + it('does not clear session if provider failed to authenticate request with non-401 reason with active session.', async () => { const systemAPIRequest = requestFixture({ headers: { xCustomHeader: 'xxx' } }); diff --git a/x-pack/plugins/security/server/lib/authentication/authentication_result.test.ts b/x-pack/plugins/security/server/lib/authentication/authentication_result.test.ts index d67136e21a5c5..870e843a829b0 100644 --- a/x-pack/plugins/security/server/lib/authentication/authentication_result.test.ts +++ b/x-pack/plugins/security/server/lib/authentication/authentication_result.test.ts @@ -123,4 +123,96 @@ describe('AuthenticationResult', () => { expect(authenticationResult.error).toBeUndefined(); }); }); + + describe('shouldUpdateState', () => { + it('always `false` for `failed`', () => { + expect(AuthenticationResult.failed(new Error('error')).shouldUpdateState()).toBe(false); + }); + + it('always `false` for `notHandled`', () => { + expect(AuthenticationResult.notHandled().shouldUpdateState()).toBe(false); + }); + + it('depends on `state` for `redirected`.', () => { + const mockURL = 'some-url'; + expect(AuthenticationResult.redirectTo(mockURL, 'string').shouldUpdateState()).toBe(true); + expect(AuthenticationResult.redirectTo(mockURL, 0).shouldUpdateState()).toBe(true); + expect(AuthenticationResult.redirectTo(mockURL, true).shouldUpdateState()).toBe(true); + expect(AuthenticationResult.redirectTo(mockURL, false).shouldUpdateState()).toBe(true); + expect(AuthenticationResult.redirectTo(mockURL, { prop: 'object' }).shouldUpdateState()).toBe( + true + ); + expect(AuthenticationResult.redirectTo(mockURL, { prop: 'object' }).shouldUpdateState()).toBe( + true + ); + + expect(AuthenticationResult.redirectTo(mockURL).shouldUpdateState()).toBe(false); + expect(AuthenticationResult.redirectTo(mockURL, undefined).shouldUpdateState()).toBe(false); + expect(AuthenticationResult.redirectTo(mockURL, null).shouldUpdateState()).toBe(false); + }); + + it('depends on `state` for `succeeded`.', () => { + const mockUser = { username: 'u' }; + expect(AuthenticationResult.succeeded(mockUser, 'string').shouldUpdateState()).toBe(true); + expect(AuthenticationResult.succeeded(mockUser, 0).shouldUpdateState()).toBe(true); + expect(AuthenticationResult.succeeded(mockUser, true).shouldUpdateState()).toBe(true); + expect(AuthenticationResult.succeeded(mockUser, false).shouldUpdateState()).toBe(true); + expect(AuthenticationResult.succeeded(mockUser, { prop: 'object' }).shouldUpdateState()).toBe( + true + ); + expect(AuthenticationResult.succeeded(mockUser, { prop: 'object' }).shouldUpdateState()).toBe( + true + ); + + expect(AuthenticationResult.succeeded(mockUser).shouldUpdateState()).toBe(false); + expect(AuthenticationResult.succeeded(mockUser, undefined).shouldUpdateState()).toBe(false); + expect(AuthenticationResult.succeeded(mockUser, null).shouldUpdateState()).toBe(false); + }); + }); + + describe('shouldClearState', () => { + it('always `false` for `failed`', () => { + expect(AuthenticationResult.failed(new Error('error')).shouldClearState()).toBe(false); + }); + + it('always `false` for `notHandled`', () => { + expect(AuthenticationResult.notHandled().shouldClearState()).toBe(false); + }); + + it('depends on `state` for `redirected`.', () => { + const mockURL = 'some-url'; + expect(AuthenticationResult.redirectTo(mockURL, null).shouldClearState()).toBe(true); + + expect(AuthenticationResult.redirectTo(mockURL).shouldClearState()).toBe(false); + expect(AuthenticationResult.redirectTo(mockURL, undefined).shouldClearState()).toBe(false); + expect(AuthenticationResult.redirectTo(mockURL, 'string').shouldClearState()).toBe(false); + expect(AuthenticationResult.redirectTo(mockURL, 0).shouldClearState()).toBe(false); + expect(AuthenticationResult.redirectTo(mockURL, true).shouldClearState()).toBe(false); + expect(AuthenticationResult.redirectTo(mockURL, false).shouldClearState()).toBe(false); + expect(AuthenticationResult.redirectTo(mockURL, { prop: 'object' }).shouldClearState()).toBe( + false + ); + expect(AuthenticationResult.redirectTo(mockURL, { prop: 'object' }).shouldClearState()).toBe( + false + ); + }); + + it('depends on `state` for `succeeded`.', () => { + const mockUser = { username: 'u' }; + expect(AuthenticationResult.succeeded(mockUser, null).shouldClearState()).toBe(true); + + expect(AuthenticationResult.succeeded(mockUser).shouldClearState()).toBe(false); + expect(AuthenticationResult.succeeded(mockUser, undefined).shouldClearState()).toBe(false); + expect(AuthenticationResult.succeeded(mockUser, 'string').shouldClearState()).toBe(false); + expect(AuthenticationResult.succeeded(mockUser, 0).shouldClearState()).toBe(false); + expect(AuthenticationResult.succeeded(mockUser, true).shouldClearState()).toBe(false); + expect(AuthenticationResult.succeeded(mockUser, false).shouldClearState()).toBe(false); + expect(AuthenticationResult.succeeded(mockUser, { prop: 'object' }).shouldClearState()).toBe( + false + ); + expect(AuthenticationResult.succeeded(mockUser, { prop: 'object' }).shouldClearState()).toBe( + false + ); + }); + }); }); diff --git a/x-pack/plugins/security/server/lib/authentication/authentication_result.ts b/x-pack/plugins/security/server/lib/authentication/authentication_result.ts index 19df30ef84ae9..b6a0d3ba1c21a 100644 --- a/x-pack/plugins/security/server/lib/authentication/authentication_result.ts +++ b/x-pack/plugins/security/server/lib/authentication/authentication_result.ts @@ -160,4 +160,19 @@ export class AuthenticationResult { public redirected() { return this.status === AuthenticationResultStatus.Redirected; } + + /** + * Checks whether authentication result implies state update. + */ + public shouldUpdateState() { + // State shouldn't be updated in case it wasn't set or was specifically set to `null`. + return this.options.state != null; + } + + /** + * Checks whether authentication result implies state clearing. + */ + public shouldClearState() { + return this.options.state === null; + } } diff --git a/x-pack/plugins/security/server/lib/authentication/authenticator.js b/x-pack/plugins/security/server/lib/authentication/authenticator.js index 2cf2d0e1e0f8b..f6dacb308e62d 100644 --- a/x-pack/plugins/security/server/lib/authentication/authenticator.js +++ b/x-pack/plugins/security/server/lib/authentication/authenticator.js @@ -6,6 +6,7 @@ import { getClient } from '../../../../../server/lib/get_client_shield'; import { AuthScopeService } from '../auth_scope_service'; +import { getErrorStatusCode } from '../errors'; import { BasicAuthenticationProvider } from './providers/basic'; import { SAMLAuthenticationProvider } from './providers/saml'; import { TokenAuthenticationProvider } from './providers/token'; @@ -49,15 +50,6 @@ function getProviderOptions(server) { }; } -/** - * Extracts error code from Boom and Elasticsearch "native" errors. - * @param {Error} error Error instance to extract status code from. - * @returns {number} - */ -function getErrorStatusCode(error) { - return error.isBoom ? error.output.statusCode : error.statusCode; -} - /** * Authenticator is responsible for authentication of the request using chain of * authentication providers. The chain is essentially a prioritized list of configured @@ -149,21 +141,24 @@ class Authenticator { ownsSession ? existingSession.state : null ); - if (ownsSession || authenticationResult.state) { + if (ownsSession || authenticationResult.shouldUpdateState()) { // If authentication succeeds or requires redirect we should automatically extend existing user session, // unless authentication has been triggered by a system API request. In case provider explicitly returns new // state we should store it in the session regardless of whether it's a system API request or not. const sessionCanBeUpdated = (authenticationResult.succeeded() || authenticationResult.redirected()) - && (authenticationResult.state || !isSystemApiRequest); - - // If provider owned the session, but failed to authenticate anyway, that likely means - // that session is not valid and we should clear it. - if (authenticationResult.failed() && getErrorStatusCode(authenticationResult.error) === 401) { + && (authenticationResult.shouldUpdateState() || !isSystemApiRequest); + + // If provider owned the session, but failed to authenticate anyway, that likely means that + // session is not valid and we should clear it. Also provider can specifically ask to clear + // session by setting it to `null` even if authentication attempt didn't fail. + if (authenticationResult.shouldClearState() || ( + authenticationResult.failed() && getErrorStatusCode(authenticationResult.error) === 401) + ) { await this._session.clear(request); } else if (sessionCanBeUpdated) { await this._session.set( request, - authenticationResult.state + authenticationResult.shouldUpdateState() ? { state: authenticationResult.state, provider: providerType } : existingSession ); diff --git a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js index ebc33d6b7f596..b13fc1ce8934f 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js +++ b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js @@ -6,6 +6,7 @@ import expect from '@kbn/expect'; import sinon from 'sinon'; +import { errors } from 'elasticsearch'; import { requestFixture } from '../../../__tests__/__fixtures__/request'; import { LoginAttempt } from '../../login_attempt'; import { TokenAuthenticationProvider } from '../token'; @@ -327,6 +328,58 @@ describe('TokenAuthenticationProvider', () => { expect(authenticationResult.error).to.be.eql(authenticationError); }); + it('redirects non-AJAX requests to /login and clears session if token refresh fails with 400 error', async () => { + const request = requestFixture({ path: '/some-path' }); + + callWithRequest + .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate') + .rejects({ body: { error: { reason: 'token expired' } } }); + + callWithInternalUser + .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } }) + .rejects(new errors.BadRequest('failed to refresh token')); + + const accessToken = 'foo'; + const refreshToken = 'bar'; + const authenticationResult = await provider.authenticate(request, { accessToken, refreshToken }); + + sinon.assert.calledOnce(callWithRequest); + sinon.assert.calledOnce(callWithInternalUser); + + expect(request.headers).to.not.have.property('authorization'); + expect(authenticationResult.redirected()).to.be(true); + expect(authenticationResult.redirectURL).to.be('/base-path/login?next=%2Fsome-path'); + expect(authenticationResult.user).to.be.eql(undefined); + expect(authenticationResult.state).to.be.eql(null); + expect(authenticationResult.error).to.be.eql(undefined); + }); + + it('does not redirect AJAX requests if token refresh fails with 400 error', async () => { + const request = requestFixture({ headers: { 'kbn-xsrf': 'xsrf' }, path: '/some-path' }); + + callWithRequest + .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate') + .rejects({ body: { error: { reason: 'token expired' } } }); + + const authenticationError = new errors.BadRequest('failed to refresh token'); + callWithInternalUser + .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } }) + .rejects(authenticationError); + + const accessToken = 'foo'; + const refreshToken = 'bar'; + const authenticationResult = await provider.authenticate(request, { accessToken, refreshToken }); + + sinon.assert.calledOnce(callWithRequest); + sinon.assert.calledOnce(callWithInternalUser); + + expect(request.headers).to.not.have.property('authorization'); + expect(authenticationResult.failed()).to.be(true); + expect(authenticationResult.error).to.be(authenticationError); + expect(authenticationResult.user).to.be.eql(undefined); + expect(authenticationResult.state).to.be.eql(undefined); + }); + it('fails if new access token is rejected after successful refresh', async () => { const request = requestFixture(); diff --git a/x-pack/plugins/security/server/lib/authentication/providers/token.js b/x-pack/plugins/security/server/lib/authentication/providers/token.js index 74056bce742ce..96d3c304c3445 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/token.js +++ b/x-pack/plugins/security/server/lib/authentication/providers/token.js @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { getErrorStatusCode } from '../../errors'; import { canRedirectRequest } from '../../can_redirect_request'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; @@ -91,10 +92,7 @@ export class TokenAuthenticationProvider { // finally, if authentication still can not be handled for this // request/state combination, redirect to the login page if appropriate if (authenticationResult.notHandled() && canRedirectRequest(request)) { - const nextURL = encodeURIComponent(`${request.getBasePath()}${request.url.path}`); - authenticationResult = AuthenticationResult.redirectTo( - `${this._options.basePath}/login?next=${nextURL}` - ); + authenticationResult = AuthenticationResult.redirectTo(this._getLoginPageURL(request)); } return authenticationResult; @@ -356,7 +354,30 @@ export class TokenAuthenticationProvider { // it's called with this request once again down the line (e.g. in the next authentication provider). delete request.headers.authorization; + // If refresh fails with `400` then refresh token is no longer valid and we should clear session + // and redirect user to the login page to re-authenticate. + if (getErrorStatusCode(err) === 400 && canRedirectRequest(request)) { + this._options.log( + ['debug', 'security', 'token'], + 'Clearing session since both access and refresh tokens are expired.' + ); + + // Set state to `null` to let `Authenticator` know that we want to clear current session. + return AuthenticationResult.redirectTo(this._getLoginPageURL(request), null); + } + return AuthenticationResult.failed(err); } } + + /** + * Constructs login page URL using current url path as `next` query string parameter. + * @param {Hapi.Request} request HapiJS request instance. + * @returns {string} + * @private + */ + _getLoginPageURL(request) { + const nextURL = encodeURIComponent(`${request.getBasePath()}${request.url.path}`); + return `${this._options.basePath}/login?next=${nextURL}`; + } } diff --git a/x-pack/plugins/security/server/lib/errors.js b/x-pack/plugins/security/server/lib/errors.js deleted file mode 100644 index 0f8a0f0d8c0a9..0000000000000 --- a/x-pack/plugins/security/server/lib/errors.js +++ /dev/null @@ -1,11 +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 { boomify } from 'boom'; - -export function wrapError(error) { - return boomify(error, { statusCode: error.status }); -} diff --git a/x-pack/plugins/security/server/lib/errors.test.ts b/x-pack/plugins/security/server/lib/errors.test.ts new file mode 100644 index 0000000000000..7c4668b245b0e --- /dev/null +++ b/x-pack/plugins/security/server/lib/errors.test.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import Boom from 'boom'; +import { errors as esErrors } from 'elasticsearch'; +import * as errors from './errors'; + +describe('lib/errors', () => { + describe('#wrapError', () => { + it('returns given object', () => { + const err = new Error(); + const returned = errors.wrapError(err); + expect(returned).toEqual(err); + }); + + it('error becomes boom error', () => { + const err = new Error(); + errors.wrapError(err); + expect(err).toHaveProperty('isBoom', true); + }); + + it('defaults output.statusCode to 500', () => { + const err = new Error(); + errors.wrapError(err); + expect(err).toHaveProperty('output.statusCode', 500); + }); + + it('sets output.statusCode to .status if given', () => { + const err: any = new Error(); + err.status = 400; + errors.wrapError(err); + expect(err).toHaveProperty('output.statusCode', 400); + }); + + it('defaults message to "Internal Server Error"', () => { + const err = new Error(); + errors.wrapError(err); + expect(err.message).toBe('Internal Server Error'); + }); + + it('sets custom message if a 400 level error', () => { + const err: any = new Error('wat'); + err.status = 499; + errors.wrapError(err); + expect(err).toHaveProperty('output.payload.message', 'wat'); + }); + }); + + describe('#getErrorStatusCode', () => { + it('extracts status code from Boom error', () => { + expect(errors.getErrorStatusCode(Boom.badRequest())).toBe(400); + expect(errors.getErrorStatusCode(Boom.unauthorized())).toBe(401); + }); + + it('extracts status code from Elasticsearch client error', () => { + expect(errors.getErrorStatusCode(new esErrors.BadRequest())).toBe(400); + expect(errors.getErrorStatusCode(new esErrors.AuthenticationException())).toBe(401); + }); + + it('extracts status code from `status` property', () => { + expect(errors.getErrorStatusCode({ statusText: 'Bad Request', status: 400 })).toBe(400); + expect(errors.getErrorStatusCode({ statusText: 'Unauthorized', status: 401 })).toBe(401); + }); + }); +}); diff --git a/x-pack/plugins/security/server/lib/errors.ts b/x-pack/plugins/security/server/lib/errors.ts new file mode 100644 index 0000000000000..e0c2918991696 --- /dev/null +++ b/x-pack/plugins/security/server/lib/errors.ts @@ -0,0 +1,19 @@ +/* + * 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 Boom from 'boom'; + +export function wrapError(error: any) { + return Boom.boomify(error, { statusCode: getErrorStatusCode(error) }); +} + +/** + * Extracts error code from Boom and Elasticsearch "native" errors. + * @param error Error instance to extract status code from. + */ +export function getErrorStatusCode(error: any): number { + return Boom.isBoom(error) ? error.output.statusCode : error.statusCode || error.status; +} From 2f9ad0a814aa7d69da29f3bbf362ca019d792049 Mon Sep 17 00:00:00 2001 From: Shaunak Kashyap Date: Tue, 26 Mar 2019 06:27:20 -0700 Subject: [PATCH 32/96] Improve performance of the Logstash Pipeline Viewer (#33793) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves #27513. _This PR is a combination of #31293 (the code changes) + #33570 (test updates). These two PRs were individually reviewed and merged into a feature branch. This combo PR here simply sets up the merge from the feature branch to `master`._ Summary of changes, taken from #31293: ## Before this PR The Logstash Pipeline Viewer UI would make a single Kibana API call to fetch all the information necessary to render the Logstash pipeline. This included information necessary to render the detail drawer that opens up when a user clicks on an individual vertex in the pipeline. Naturally, this single API call fetched _a lot_ of data, not just from the Kibana server but also, in turn, from Elasticsearch as well. The "pro" of this approach was that the user would see instantaneous results if they clicked on a vertex in a pipeline and opened the detail drawer for that vertex. The "cons" were the amount of computation Elasticsearch had to perform and the amount of data being transferred over the wire between Elasticsearch and the Kibana server as well as between the Kibana server and the browser. ## With this PR This PR makes the Kibana API call to fetch data necessary for **initially** rendering the pipeline — that is, with the detail drawer closed — much lighter. When the user clicks on a vertex in a pipeline, a second API call is then made to fetch data necessary for the detail drawer. ## Gains, by the numbers Based on a simple, 1-input, 1-filter, and 1-output pipeline. * Before this PR, the Elasticsearch `logstash_stats` API responses (multiple calls were made using the `composite` aggregation over the `date_histogram` aggregation) generated a total of 1228 aggregation buckets (before any `filter_path`s were applied but across all `composite` "pages"). With this PR, the single `logstash_stats` API response (note that this is just for the initial rendering of the pipeline, with the detail drawer closed) generated 12 buckets (also before any `filter_path`s were applied). That's a **99.02% reduction** in number of buckets. * Before this PR, the Elasticsearch `logstash_stats` API responses added up to 70319 bytes. With this PR, the single `logstash_stats` API response for the same pipeline is 746 bytes. That's a **98.93% reduction** in size. * Before this PR, the Elasticsearch `logstash_state` API response was 7718 bytes. With this PR, the API response for the same pipeline is 2328 bytes. That's a **69.83% reduction** in size. * Before this PR the Kibana API response was 51777 bytes. With this PR, the API response for the same pipeline is 2567 bytes (again, note that this is just for the initial rendering of the pipeline, with the detail drawer closed). That's a **95.04% reduction** in size. --- .../models/graph/__tests__/plugin_vertex.js | 38 +- .../models/graph/plugin_vertex.js | 34 +- .../pipeline_viewer.test.js.snap | 30 +- .../views/__test__/pipeline_viewer.test.js | 30 +- .../pipeline_viewer/views/pipeline_viewer.js | 36 +- .../public/views/logstash/pipeline/index.js | 33 +- .../lib/logstash/__tests__/get_pipeline.js | 344 ++++-------------- .../server/lib/logstash/get_pipeline.js | 94 ++--- .../logstash/get_pipeline_state_document.js | 5 +- .../get_pipeline_stats_aggregation.js | 84 ++--- .../lib/logstash/get_pipeline_versions.js | 3 +- .../lib/logstash/get_pipeline_vertex.js | 121 ++++++ .../get_pipeline_vertex_stats_aggregation.js | 189 ++++++++++ .../server/routes/api/v1/logstash/pipeline.js | 40 +- 14 files changed, 547 insertions(+), 534 deletions(-) create mode 100644 x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex.js create mode 100644 x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex_stats_aggregation.js diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js index 8d9ccc17c2829..5e158c5fa97a1 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js @@ -25,30 +25,10 @@ describe('PluginVertex', () => { vertexJson = { config_name: 'some-name', stats: { - millis_per_event: { - data: [ - [ 1516667383000, 10 ], - [ 1516667386000, 50 ] - ] - }, - percent_of_total_processor_duration: { - data: [ - [ 1516667383000, 0.25 ], - [ 1516667386000, 0.3 ] - ] - }, - events_in_per_millisecond: { - data: [ - [ 1516667383000, 0.01 ], - [ 1516667386000, 0.02 ] - ] - }, - events_out_per_millisecond: { - data: [ - [ 1516667383000, 0.01 ], - [ 1516667386000, 0.03 ] - ] - } + millis_per_event: 50, + percent_of_total_processor_duration: 0.3, + events_in_per_millisecond: 0.01, + events_out_per_millisecond: 0.01 } }; }); @@ -80,7 +60,7 @@ describe('PluginVertex', () => { it('should have the correct events-per-second stat', () => { const pluginVertex = new PluginVertex(graph, vertexJson); - expect(pluginVertex.latestEventsPerSecond).to.be(20); + expect(pluginVertex.latestEventsPerSecond).to.be(10); }); describe('isTimeConsuming', () => { @@ -91,13 +71,13 @@ describe('PluginVertex', () => { }); it('should have a false isTimeConsuming result when the plugin consumes an average amount of execution time', () => { - vertexJson.stats.percent_of_total_processor_duration.data[1][1] = percentExecution; + vertexJson.stats.percent_of_total_processor_duration = percentExecution; const pluginVertex = new PluginVertex(graph, vertexJson); expect(pluginVertex.isTimeConsuming()).to.be(false); }); it('should have a true isTimeConsuming result when the plugin consumes a large amount of execution time', () => { - vertexJson.stats.percent_of_total_processor_duration.data[1][1] = 0.1 + + vertexJson.stats.percent_of_total_processor_duration = 0.1 + (percentExecution * (TIME_CONSUMING_PROCESSOR_THRESHOLD_COEFFICIENT)); const pluginVertex = new PluginVertex(graph, vertexJson); expect(pluginVertex.isTimeConsuming()).to.be(true); @@ -111,13 +91,13 @@ describe('PluginVertex', () => { }); it('should have a true isSlow result when the plugin\'s seconds per event is 2 standard deviations above the mean', () => { - vertexJson.stats.millis_per_event.data[1][1] = 999999999999999999; + vertexJson.stats.millis_per_event = 999999999999999999; const pluginVertex = new PluginVertex(graph, vertexJson); expect(pluginVertex.isSlow()).to.be(true); }); it('should have a false isSlow result when the plugin\'s seconds per event is 2 standard deviations above the mean', () => { - vertexJson.stats.millis_per_event.data[1][1] = 1; + vertexJson.stats.millis_per_event = 1; const pluginVertex = new PluginVertex(graph, vertexJson); expect(pluginVertex.isSlow()).to.be(false); }); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js index 0c74318982bd3..23f316a9351ca 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { last, get, omit } from 'lodash'; +import { get } from 'lodash'; import { Vertex } from './vertex'; export const TIME_CONSUMING_PROCESSOR_THRESHOLD_COEFFICIENT = 2; @@ -44,28 +44,36 @@ export class PluginVertex extends Vertex { } get latestMillisPerEvent() { - const latestMillisPerEventBucket = last(get(this.stats, 'millis_per_event.data', [])) || []; - return latestMillisPerEventBucket[1]; + return get(this.stats, 'millis_per_event'); } get percentOfTotalProcessorTime() { - const latestPercentOfTotalProcessorDurationBucket = last(get(this.stats, 'percent_of_total_processor_duration.data', [])) || []; - return latestPercentOfTotalProcessorDurationBucket[1]; + return get(this.stats, 'percent_of_total_processor_duration'); } - get eventsPerSecond() { - const eventsPerMillisecond = this.isInput + get eventsPerMillisecond() { + return this.isInput ? this.stats.events_out_per_millisecond : this.stats.events_in_per_millisecond; - return { - ...omit(eventsPerMillisecond, 'data'), - data: get(eventsPerMillisecond, 'data', []).map(([x, y]) => [x, y * 1000]) - }; + } + + get eventsPerSecond() { + if (!this.eventsPerMillisecond.hasOwnProperty('data')) { + return this.eventsPerMillisecond * 1000; + } + + const eps = { ...this.eventsPerMillisecond }; // Clone the object so we don't modify the original one + eps.data = this.eventsPerMillisecond.data.map(([timestamp, value]) => [ timestamp, value * 1000]); + return eps; } get latestEventsPerSecond() { - const latestBucket = last(get(this.eventsPerSecond, 'data', [])) || []; - return latestBucket[1]; + if (!this.eventsPerSecond.hasOwnProperty('data')) { + return this.eventsPerSecond; + } + + const numTimeseriesBuckets = this.eventsPerSecond.data.length; + return this.eventsPerSecond.data[numTimeseriesBuckets - 1][1]; } isTimeConsuming() { diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/pipeline_viewer.test.js.snap b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/pipeline_viewer.test.js.snap index fb22a53cf25b0..aaa012c7a534e 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/pipeline_viewer.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/pipeline_viewer.test.js.snap @@ -14,7 +14,6 @@ exports[`PipelineViewer component passes expected props 1`] = ` verticalPosition="center" > @@ -90,11 +87,6 @@ exports[`PipelineViewer component renders DetailDrawer when selected vertex is n verticalPosition="center" > { let pipeline; @@ -44,7 +43,7 @@ describe('PipelineViewer component', () => { }, }; - component = ; + component = ; }); it('passes expected props', () => { @@ -53,33 +52,12 @@ describe('PipelineViewer component', () => { expect(renderedComponent).toMatchSnapshot(); }); - it('changes selected vertex', () => { - const vertex = { id: 'stdin' }; - - const instance = shallowWithIntl(component).instance(); - instance.onShowVertexDetails(vertex); - - expect(get(instance, 'state.detailDrawer.vertex')).toBe(vertex); - }); - - it('toggles selected vertex on second pass', () => { - const vertex = { id: 'stdin' }; - - const instance = shallowWithIntl(component).instance(); - instance.onShowVertexDetails(vertex); - instance.onShowVertexDetails(vertex); - - expect(get(instance, 'state.detailDrawer.vertex')).toBeNull(); - }); - it('renders DetailDrawer when selected vertex is not null', () => { const vertex = { id: 'stdin' }; + component = ; - const wrapper = shallowWithIntl(component); - const instance = wrapper.instance(); - instance.onShowVertexDetails(vertex); - wrapper.update(); + const renderedComponent = shallowWithIntl(component); - expect(wrapper).toMatchSnapshot(); + expect(renderedComponent).toMatchSnapshot(); }); }); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/pipeline_viewer.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/pipeline_viewer.js index ddebfc74fb53a..64970a846f0bf 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/pipeline_viewer.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/pipeline_viewer.js @@ -27,36 +27,15 @@ class PipelineViewerUi extends React.Component { }; } - onShowVertexDetails = (vertex) => { - if (vertex === this.state.detailDrawer.vertex) { - this.onHideVertexDetails(); - } - else { - this.setState({ - detailDrawer: { - vertex - } - }); - } - } - - onHideVertexDetails = () => { - this.setState({ - detailDrawer: { - vertex: null - } - }); - } - renderDetailDrawer = () => { - if (!this.state.detailDrawer.vertex) { + if (!this.props.detailVertex) { return null; } return ( this.props.setDetailVertexId(undefined)} timeseriesTooltipXValueFormatter={this.props.timeseriesTooltipXValueFormatter} /> ); @@ -79,8 +58,7 @@ class PipelineViewerUi extends React.Component { iconType="logstashInput" headingText={intl.formatMessage({ id: 'xpack.monitoring.logstash.pipelineViewer.inputsTitle', defaultMessage: 'Inputs' })} elements={inputs} - onShowVertexDetails={this.onShowVertexDetails} - detailVertex={this.state.detailDrawer.vertex} + onShowVertexDetails={this.props.setDetailVertexId} /> @@ -89,16 +67,14 @@ class PipelineViewerUi extends React.Component { iconType="logstashFilter" headingText={intl.formatMessage({ id: 'xpack.monitoring.logstash.pipelineViewer.filtersTitle', defaultMessage: 'Filters' })} elements={filters} - onShowVertexDetails={this.onShowVertexDetails} - detailVertex={this.state.detailDrawer.vertex} + onShowVertexDetails={this.props.setDetailVertexId} /> { this.renderDetailDrawer() } diff --git a/x-pack/plugins/monitoring/public/views/logstash/pipeline/index.js b/x-pack/plugins/monitoring/public/views/logstash/pipeline/index.js index 671cdd3a1b609..9ff09d731c48a 100644 --- a/x-pack/plugins/monitoring/public/views/logstash/pipeline/index.js +++ b/x-pack/plugins/monitoring/public/views/logstash/pipeline/index.js @@ -20,6 +20,7 @@ import { List } from 'plugins/monitoring/components/logstash/pipeline_viewer/mod import { PipelineState } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/pipeline_state'; import { PipelineViewer } from 'plugins/monitoring/components/logstash/pipeline_viewer'; import { Pipeline } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/pipeline'; +import { vertexFactory } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/graph/vertex_factory'; import { MonitoringViewBaseController } from '../../base_controller'; import { I18nContext } from 'ui/i18n'; import { @@ -28,6 +29,9 @@ import { EuiPageContent, } from '@elastic/eui'; +let previousPipelineHash = undefined; +let detailVertexId = undefined; + function getPageData($injector) { const $route = $injector.get('$route'); const $http = $injector.get('$http'); @@ -38,11 +42,20 @@ function getPageData($injector) { const { ccs, cluster_uuid: clusterUuid } = globalState; const pipelineId = $route.current.params.id; const pipelineHash = $route.current.params.hash || ''; + + // Pipeline version was changed, so clear out detailVertexId since that vertex won't + // exist in the updated pipeline version + if (pipelineHash !== previousPipelineHash) { + previousPipelineHash = pipelineHash; + detailVertexId = undefined; + } + const url = pipelineHash ? `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipeline/${pipelineId}/${pipelineHash}` : `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipeline/${pipelineId}`; return $http.post(url, { - ccs + ccs, + detailVertexId }) .then(response => response.data) .then(data => { @@ -107,11 +120,22 @@ uiRoutes.when('/logstash/pipelines/:id/:hash?', { const timeseriesTooltipXValueFormatter = xValue => moment(xValue).format(dateFormat); + const setDetailVertexId = vertex => { + if (!vertex) { + detailVertexId = undefined; + } else { + detailVertexId = vertex.id; + } + + return this.updateData(); + }; + $scope.$watch(() => this.data, data => { if (!data || !data.pipeline) { return; } this.pipelineState = new PipelineState(data.pipeline); + this.detailVertex = data.vertex ? vertexFactory(null, data.vertex) : null; this.renderReact( @@ -122,6 +146,8 @@ uiRoutes.when('/logstash/pipelines/:id/:hash?', { Pipeline.fromPipelineGraph(this.pipelineState.config.graph) )} timeseriesTooltipXValueFormatter={timeseriesTooltipXValueFormatter} + setDetailVertexId={setDetailVertexId} + detailVertex={this.detailVertex} /> @@ -129,6 +155,11 @@ uiRoutes.when('/logstash/pipelines/:id/:hash?', { ); }); + + $scope.$on('$destroy', () => { + previousPipelineHash = undefined; + detailVertexId = undefined; + }); } } }); diff --git a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js index f0e81eb63dddc..71732b6a2d7fa 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js @@ -37,13 +37,8 @@ describe('get_pipeline', () => { it('returns correct stats', () => { const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds); expect(result).to.eql({ - events_in: 10000, - events_out: 9000, - duration_in_millis: 18000, events_out_per_millisecond: 0.01, millis_per_event: 2, - queue_push_duration_in_millis: 100000, - queue_push_duration_in_millis_per_event: 11.11111111111111 }); }); @@ -57,9 +52,6 @@ describe('get_pipeline', () => { it('returns correct stats', () => { const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds); expect(result).to.eql({ - events_in: 10000, - events_out: 9000, - duration_in_millis: 18000, events_in_per_millisecond: 0.011111111111111112, events_out_per_millisecond: 0.01, millis_per_event: 1.8, @@ -78,9 +70,6 @@ describe('get_pipeline', () => { it('returns correct stats', () => { const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds); expect(result).to.eql({ - events_in: 10000, - events_out: 9000, - duration_in_millis: 18000, events_in_per_millisecond: 0.011111111111111112, events_out_per_millisecond: 0.01, millis_per_event: 1.8, @@ -93,7 +82,6 @@ describe('get_pipeline', () => { describe('_enrichStateWithStatsAggregation function', () => { let stateDocument; let statsAggregation; - let version; let timeseriesInterval; beforeEach(() => { @@ -160,278 +148,96 @@ describe('get_pipeline', () => { }; statsAggregation = { - timeseriesStats: [ - { - key: { time_bucket: 1516131120000 }, - pipelines: { - scoped: { - vertices: { - vertex_id: { - buckets: [ - { - key: 'mystdout', - events_in_total: { value: 1000 }, - events_out_total: { value: 1000 }, - duration_in_millis_total: { value: 15 }, - queue_push_duration_in_millis_total: { value: 0 } - }, - { - key: 'mystdin', - events_in_total: { value: 0 }, - events_out_total: { value: 1000 }, - duration_in_millis_total: { value: 0 }, - queue_push_duration_in_millis_total: { value: 13547 } - } - ] - } - }, - total_processor_duration_stats: { - count: 276, - min: 0, - max: 15904756, - avg: 6591773.384057971, - sum: 1819329454 - } - } - } - }, - { - key: { time_bucket: 1516131180000 }, - pipelines: { - scoped: { - vertices: { - vertex_id: { - buckets: [ - { - key: 'mystdout', - events_in_total: { value: 2000 }, - events_out_total: { value: 2000 }, - duration_in_millis_total: { value: 20 }, - queue_push_duration_in_millis_total: { value: 0 } - }, - { - key: 'mystdin', - events_in_total: { value: 0 }, - events_out_total: { value: 2000 }, - duration_in_millis_total: { value: 0 }, - queue_push_duration_in_millis_total: { value: 25073 } - } - ] - } - }, - total_processor_duration_stats: { - count: 276, - min: 0, - max: 15953756, - avg: 6591773.384057971, - sum: 1819329454 + aggregations: { + pipelines: { + scoped: { + vertices: { + vertex_id: { + buckets: [ + { + key: 'mystdout', + events_in_total: { value: 1000 }, + events_out_total: { value: 1000 }, + duration_in_millis_total: { value: 15 }, + }, + { + key: 'mystdin', + events_in_total: { value: 0 }, + events_out_total: { value: 1000 }, + duration_in_millis_total: { value: 0 }, + } + ] } + }, + total_processor_duration_stats: { + count: 276, + min: 0, + max: 15904756, + avg: 6591773.384057971, + sum: 1819329454 } } } - ] - }; - - version = { - hash: 'eada8baceee81726f6be9d0a071beefad3d9a2fd1b5f5d916011dca9fa66d081', - firstSeen: 1516131138639, - lastSeen: 1516135440463 + } }; - timeseriesInterval = 30; }); it('enriches the state document correctly with stats', () => { - const enrichedStateDocument = _enrichStateWithStatsAggregation(stateDocument, statsAggregation, version, timeseriesInterval); + const enrichedStateDocument = _enrichStateWithStatsAggregation(stateDocument, statsAggregation, timeseriesInterval); expect(enrichedStateDocument).to.eql({ - pipeline: { - batch_size: 125, - ephemeral_id: '2c53e689-62e8-4ef3-bc57-ea968531a848', + batch_size: 125, + ephemeral_id: '2c53e689-62e8-4ef3-bc57-ea968531a848', + hash: 'eada8baceee81726f6be9d0a071beefad3d9a2fd1b5f5d916011dca9fa66d081', + id: 'main', + representation: { + type: 'lir', + version: '0.0.0', hash: 'eada8baceee81726f6be9d0a071beefad3d9a2fd1b5f5d916011dca9fa66d081', - id: 'main', - representation: { - type: 'lir', - version: '0.0.0', - hash: 'eada8baceee81726f6be9d0a071beefad3d9a2fd1b5f5d916011dca9fa66d081', - graph: { - vertices: [ - { - config_name: 'stdin', - id: 'mystdin', - type: 'plugin', - plugin_type: 'input', - stats: { - duration_in_millis: { - data: [ - [ 1516131120000, 0 ], - [ 1516131180000, 0 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - events_in: { - data: [ - [ 1516131120000, 0 ], - [ 1516131180000, 0 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - events_out: { - data: [ - [ 1516131120000, 1000 ], - [ 1516131180000, 2000 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - events_out_per_millisecond: { - data: [ - [ 1516131120000, 0.03333333333333333 ], - [ 1516131180000, 0.06666666666666667 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - millis_per_event: { - data: [ - [ 1516131120000, 0 ], - [ 1516131180000, 0 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - queue_push_duration_in_millis: { - data: [ - [ 1516131120000, 13547 ], - [ 1516131180000, 25073 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - queue_push_duration_in_millis_per_event: { - data: [ - [ 1516131120000, 13.547 ], - [ 1516131180000, 12.5365 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - } - } - }, - { - config_name: 'stdout', - id: 'mystdout', - type: 'plugin', - plugin_type: 'output', - stats: { - duration_in_millis: { - data: [ - [ 1516131120000, 15 ], - [ 1516131180000, 20 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - events_in: { - data: [ - [ 1516131120000, 1000 ], - [ 1516131180000, 2000 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - events_out: { - data: [ - [ 1516131120000, 1000 ], - [ 1516131180000, 2000 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - events_in_per_millisecond: { - data: [ - [1516131120000, 0.03333333333333333], - [1516131180000, 0.06666666666666667] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - events_out_per_millisecond: { - data: [ - [ 1516131120000, 0.03333333333333333 ], - [ 1516131180000, 0.06666666666666667 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - millis_per_event: { - data: [ - [ 1516131120000, 0.015 ], - [ 1516131180000, 0.01 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - }, - percent_of_total_processor_duration: { - data: [ - [ 1516131120000, 0.0000009431141225932671 ], - [ 1516131180000, 0.0000012536232846986 ] - ], - timeRange: { - min: 1516131138639, - max: 1516135440463 - } - } - } + graph: { + vertices: [ + { + config_name: 'stdin', + id: 'mystdin', + type: 'plugin', + plugin_type: 'input', + stats: { + events_out_per_millisecond: 0.03333333333333333, + millis_per_event: 0 } - ], - edges: [ - { - id: 'c56369ba2e160c8add43e8f105ca17c374b27f4b4627ea4566f066b0ead0bcc7', - from: 'mystdin', - to: '__QUEUE__', - type: 'plain' - }, - { - id: '8a5222282b023399a14195011f2a14aa54a4d97810cd9e0a63c5cd98856bb70f', - from: '__QUEUE__', - to: 'mystdout', - type: 'plain' + }, + { + config_name: 'stdout', + id: 'mystdout', + type: 'plugin', + plugin_type: 'output', + stats: { + events_in_per_millisecond: 0.03333333333333333, + events_out_per_millisecond: 0.03333333333333333, + millis_per_event: 0.015, + percent_of_total_processor_duration: 0.0000009431141225932671 } - ] - }, - plugins: [] + } + ], + edges: [ + { + id: 'c56369ba2e160c8add43e8f105ca17c374b27f4b4627ea4566f066b0ead0bcc7', + from: 'mystdin', + to: '__QUEUE__', + type: 'plain' + }, + { + id: '8a5222282b023399a14195011f2a14aa54a4d97810cd9e0a63c5cd98856bb70f', + from: '__QUEUE__', + to: 'mystdout', + type: 'plain' + } + ] }, - workers: 1 - } + plugins: [] + }, + workers: 1 }); }); }); diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js index 63f0f2389033a..8461f880e37f5 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js @@ -9,7 +9,6 @@ import { get } from 'lodash'; import { checkParam } from '../error_missing_required'; import { getPipelineStateDocument } from './get_pipeline_state_document'; import { getPipelineStatsAggregation } from './get_pipeline_stats_aggregation'; -import { getPipelineVersions } from './get_pipeline_versions'; import { calculateTimeseriesInterval } from '../calculate_timeseries_interval'; export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds) { @@ -24,7 +23,6 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI const durationInMillis = vertexStatsBucket.duration_in_millis_total.value; - const inputStats = {}; const processorStats = {}; const eventsProcessedStats = { events_out_per_millisecond: eventsOutTotal / timeseriesIntervalInMillis @@ -34,8 +32,6 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI if (isInput) { eventsTotal = eventsOutTotal; - inputStats.queue_push_duration_in_millis = vertexStatsBucket.queue_push_duration_in_millis_total.value; - inputStats.queue_push_duration_in_millis_per_event = inputStats.queue_push_duration_in_millis / eventsTotal; } if (isProcessor) { @@ -45,11 +41,7 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI } return { - events_in: eventsInTotal, - events_out: eventsOutTotal, - duration_in_millis: durationInMillis, millis_per_event: durationInMillis / eventsTotal, - ...inputStats, ...processorStats, ...eventsProcessedStats }; @@ -57,15 +49,15 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI /** * The UI needs a list of all vertices for the requested pipeline version, with each vertex in the list having its timeseries metrics associated with it. The - * stateDocument object provides the list of vertices while the statsAggregation object provides timeseries metrics. This function stitches the two together - * and returns the modified stateDocument object. + * stateDocument object provides the list of vertices while the statsAggregation object provides the latest metrics for each of these vertices. + * This function stitches the two together and returns the modified stateDocument object. * * @param {Object} stateDocument * @param {Object} statsAggregation * @param {Object} First and last seen timestamps for pipeline version we're getting data for * @param {Integer} timeseriesIntervalInSeconds The size of each timeseries bucket, in seconds */ -export function _enrichStateWithStatsAggregation(stateDocument, statsAggregation, { firstSeen, lastSeen }, timeseriesIntervalInSeconds) { +export function _enrichStateWithStatsAggregation(stateDocument, statsAggregation, timeseriesIntervalInSeconds) { const logstashState = stateDocument.logstash_state; const vertices = logstashState.pipeline.representation.graph.vertices; @@ -75,67 +67,27 @@ export function _enrichStateWithStatsAggregation(stateDocument, statsAggregation vertex.stats = {}; }); - // The statsAggregation object buckets by time first, then by vertex ID. However, the logstashState object (which is part of the - // stateDocument object) buckets by vertex ID first. The UI desires the latter structure so it can look up stats by vertex. So we - // transpose statsAggregation to bucket by vertex ID first, then by time. This then allows us to stitch the per-vertex timeseries stats - // from the transposed statsAggregation object onto the logstashState object. - const timeseriesBuckets = statsAggregation.timeseriesStats; - timeseriesBuckets.forEach(timeseriesBucket => { - // each bucket calculates stats for total pipeline CPU time for the associated timeseries - const totalDurationStats = timeseriesBucket.pipelines.scoped.total_processor_duration_stats; - const totalProcessorsDurationInMillis = totalDurationStats.max - totalDurationStats.min; - - // Each timeseriesBucket contains a list of vertices and their stats for a single timeseries interval - const timestamp = timeseriesBucket.key.time_bucket; - const vertexStatsByIdBuckets = get(timeseriesBucket, 'pipelines.scoped.vertices.vertex_id.buckets', []); - - vertexStatsByIdBuckets.forEach(vertexStatsBucket => { - // Each vertexStats bucket contains a list of stats for a single vertex within a single timeseries interval - const vertexId = vertexStatsBucket.key; - const vertex = verticesById[vertexId]; - - if (vertex !== undefined) { - // We extract this vertex's stats from vertexStatsBucket - const vertexStats = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds); - - // For each stat (metric), we add it to the stats property of the vertex object in logstashState - const metrics = Object.keys(vertexStats); - metrics.forEach(metric => { - // Create metric object if it doesn't already exist - if (!vertex.stats.hasOwnProperty(metric)) { - vertex.stats[metric] = { - timeRange: { - min: firstSeen, - max: lastSeen - }, - data: [] - }; - } - - vertex.stats[metric].data.push([ timestamp, vertexStats[metric]]); - }); - } - }); + const totalDurationStats = statsAggregation.aggregations.pipelines.scoped.total_processor_duration_stats; + const totalProcessorsDurationInMillis = totalDurationStats.max - totalDurationStats.min; + + const verticesWithStatsBuckets = statsAggregation.aggregations.pipelines.scoped.vertices.vertex_id.buckets; + verticesWithStatsBuckets.forEach(vertexStatsBucket => { + // Each vertexStats bucket contains a list of stats for a single vertex within a single timeseries interval + const vertexId = vertexStatsBucket.key; + const vertex = verticesById[vertexId]; + + if (vertex !== undefined) { + // We extract this vertex's stats from vertexStatsBucket + vertex.stats = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds); + } }); - return stateDocument.logstash_state; + return stateDocument.logstash_state.pipeline; } -export async function getPipeline(req, config, lsIndexPattern, clusterUuid, pipelineId, pipelineHash) { +export async function getPipeline(req, config, lsIndexPattern, clusterUuid, pipelineId, version) { checkParam(lsIndexPattern, 'lsIndexPattern in getPipeline'); - const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); - const versions = await getPipelineVersions(callWithRequest, req, config, lsIndexPattern, clusterUuid, pipelineId); - - let version; - if (pipelineHash) { - // Find version corresponding to given hash - version = versions.find(({ hash }) => hash === pipelineHash); - } else { - // Go with latest version - version = versions[0]; - } - const options = { clusterUuid, pipelineId, @@ -147,17 +99,13 @@ export async function getPipeline(req, config, lsIndexPattern, clusterUuid, pipe const timeseriesInterval = calculateTimeseriesInterval(version.firstSeen, version.lastSeen, minIntervalSeconds); const [ stateDocument, statsAggregation ] = await Promise.all([ - getPipelineStateDocument(callWithRequest, req, lsIndexPattern, options), - getPipelineStatsAggregation(callWithRequest, req, lsIndexPattern, timeseriesInterval, options) + getPipelineStateDocument(req, lsIndexPattern, options), + getPipelineStatsAggregation(req, lsIndexPattern, timeseriesInterval, options), ]); if (stateDocument === null) { return boom.notFound(`Pipeline [${pipelineId} @ ${version.hash}] not found in the selected time range for cluster [${clusterUuid}].`); } - const result = { - ..._enrichStateWithStatsAggregation(stateDocument, statsAggregation, version, timeseriesInterval), - versions - }; - return result; + return _enrichStateWithStatsAggregation(stateDocument, statsAggregation, timeseriesInterval); } diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js index ccccb84ceb9a1..eb88342eee06f 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js @@ -8,8 +8,10 @@ import { createQuery } from '../create_query'; import { LogstashMetric } from '../metrics'; import { get } from 'lodash'; -export async function getPipelineStateDocument(callWithRequest, req, logstashIndexPattern, +export async function getPipelineStateDocument(req, logstashIndexPattern, { clusterUuid, pipelineId, version }) { + + const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); const filters = [ { term: { 'logstash_state.pipeline.id': pipelineId } }, { term: { 'logstash_state.pipeline.hash': version.hash } } @@ -32,6 +34,7 @@ export async function getPipelineStateDocument(callWithRequest, req, logstashInd size: 1, ignoreUnavailable: true, body: { + _source: { excludes: 'logstash_state.pipeline.representation.plugins' }, sort: { timestamp: { order: 'desc' } }, query, terminate_after: 1 // Safe to do because all these documents are functionally identical diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js index 49ca02e204ae2..e59299f0bd673 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { get, last } from 'lodash'; import { createQuery } from '../create_query'; import { LogstashMetric } from '../metrics'; @@ -62,7 +61,6 @@ function nestedVertices(maxBucketSize) { ...scalarCounterAggregation('events_in', fieldPath, ephemeralIdField, maxBucketSize), ...scalarCounterAggregation('events_out', fieldPath, ephemeralIdField, maxBucketSize), ...scalarCounterAggregation('duration_in_millis', fieldPath, ephemeralIdField, maxBucketSize), - ...scalarCounterAggregation('queue_push_duration_in_millis', fieldPath, ephemeralIdField, maxBucketSize) } } } @@ -90,62 +88,37 @@ function createScopedAgg(pipelineId, pipelineHash, agg) { }; } -function createTimeseriesAggs(pipelineId, pipelineHash, maxBucketSize, timeseriesInterval, lastTimeBucket) { - return { - by_time: { - composite: { - sources: [ - { - time_bucket: { - date_histogram: { - field: 'logstash_stats.timestamp', - interval: timeseriesInterval + 's' - } - } - } - ], - after: { - time_bucket: lastTimeBucket - } - }, - aggs: createScopedAgg(pipelineId, pipelineHash, { - vertices: nestedVertices(maxBucketSize), - total_processor_duration_stats: { - stats: { - field: 'logstash_stats.pipelines.events.duration_in_millis' - } - } - }) - } - }; -} - -function fetchPipelineTimeseriesStats(query, logstashIndexPattern, pipelineId, version, - maxBucketSize, timeseriesInterval, callWithRequest, req, lastTimeBucket = 0) { +function fetchPipelineLatestStats(query, logstashIndexPattern, pipelineId, version, maxBucketSize, callWithRequest, req) { const params = { index: logstashIndexPattern, size: 0, ignoreUnavailable: true, filterPath: [ - 'aggregations.by_time.buckets.key.time_bucket', - 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.key', - 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.events_in_total', - 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.events_out_total', - 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.duration_in_millis_total', - 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.queue_push_duration_in_millis_total', - 'aggregations.by_time.buckets.pipelines.scoped.total_processor_duration_stats' + 'aggregations.pipelines.scoped.vertices.vertex_id.buckets.key', + 'aggregations.pipelines.scoped.vertices.vertex_id.buckets.events_in_total', + 'aggregations.pipelines.scoped.vertices.vertex_id.buckets.events_out_total', + 'aggregations.pipelines.scoped.vertices.vertex_id.buckets.duration_in_millis_total', + 'aggregations.pipelines.scoped.total_processor_duration_stats' ], body: { query: query, - aggs: createTimeseriesAggs(pipelineId, version.hash, maxBucketSize, timeseriesInterval, lastTimeBucket) + aggs: createScopedAgg(pipelineId, version.hash, { + vertices: nestedVertices(maxBucketSize), + total_processor_duration_stats: { + stats: { + field: 'logstash_stats.pipelines.events.duration_in_millis' + } + } + }) } }; return callWithRequest(req, 'search', params); } -export async function getPipelineStatsAggregation(callWithRequest, req, logstashIndexPattern, timeseriesInterval, +export function getPipelineStatsAggregation(req, logstashIndexPattern, timeseriesInterval, { clusterUuid, start, end, pipelineId, version }) { + const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); const filters = [ { nested: { @@ -162,6 +135,9 @@ export async function getPipelineStatsAggregation(callWithRequest, req, logstash } ]; + start = version.lastSeen - (timeseriesInterval * 1000); + end = version.lastSeen; + const query = createQuery({ type: 'logstash_stats', start, @@ -173,24 +149,6 @@ export async function getPipelineStatsAggregation(callWithRequest, req, logstash const config = req.server.config(); - const timeBuckets = []; - let paginatedTimeBuckets; - do { - const lastTimeBucket = get(last(paginatedTimeBuckets), 'key.time_bucket', 0); - const paginatedResponse = await fetchPipelineTimeseriesStats(query, logstashIndexPattern, pipelineId, version, - config.get('xpack.monitoring.max_bucket_size'), timeseriesInterval, callWithRequest, req, lastTimeBucket); - - paginatedTimeBuckets = get(paginatedResponse, 'aggregations.by_time.buckets', []); - timeBuckets.push(...paginatedTimeBuckets); - } while (paginatedTimeBuckets.length > 0); - - // Drop the last bucket if it is partial (spoiler alert: this will be the case most of the time) - const lastTimeBucket = last(timeBuckets); - if (version.lastSeen - lastTimeBucket.key.time_bucket < timeseriesInterval * 1000) { - timeBuckets.pop(); - } - - return { - timeseriesStats: timeBuckets - }; + return fetchPipelineLatestStats(query, logstashIndexPattern, pipelineId, version, + config.get('xpack.monitoring.max_bucket_size'), callWithRequest, req); } diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js index b66aad3dcfcfe..39b3df6220f0f 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js @@ -10,8 +10,9 @@ import { get } from 'lodash'; import { checkParam } from '../error_missing_required'; function fetchPipelineVersions(...args) { - const [ callWithRequest, req, config, logstashIndexPattern, clusterUuid, pipelineId ] = args; + const [ req, config, logstashIndexPattern, clusterUuid, pipelineId ] = args; checkParam(logstashIndexPattern, 'logstashIndexPattern in getPipelineVersions'); + const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); const filters = [ { diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex.js new file mode 100644 index 0000000000000..f0d3fc4008b3f --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex.js @@ -0,0 +1,121 @@ +/* + * 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 boom from 'boom'; +import { get } from 'lodash'; +import { checkParam } from '../error_missing_required'; +import { getPipelineStateDocument } from './get_pipeline_state_document'; +import { getPipelineVertexStatsAggregation } from './get_pipeline_vertex_stats_aggregation'; +import { calculateTimeseriesInterval } from '../calculate_timeseries_interval'; + +export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds) { + + const isInput = vertex.plugin_type === 'input'; + const isProcessor = vertex.plugin_type === 'filter' || vertex.plugin_type === 'output'; + + const timeseriesIntervalInMillis = timeseriesIntervalInSeconds * 1000; + + const eventsInTotal = vertexStatsBucket.events_in_total.value; + const eventsOutTotal = get(vertexStatsBucket, 'events_out_total.value', null); + + const durationInMillis = vertexStatsBucket.duration_in_millis_total.value; + + const inputStats = {}; + const processorStats = {}; + const eventsProcessedStats = { + events_out_per_millisecond: eventsOutTotal / timeseriesIntervalInMillis + }; + + let eventsTotal; + + if (isInput) { + eventsTotal = eventsOutTotal; + inputStats.queue_push_duration_in_millis = vertexStatsBucket.queue_push_duration_in_millis_total.value; + inputStats.queue_push_duration_in_millis_per_event = inputStats.queue_push_duration_in_millis / eventsTotal; + } + + if (isProcessor) { + eventsTotal = eventsInTotal; + processorStats.percent_of_total_processor_duration = durationInMillis / totalProcessorsDurationInMillis; + eventsProcessedStats.events_in_per_millisecond = eventsInTotal / timeseriesIntervalInMillis; + } + + return { + events_in: eventsInTotal, + events_out: eventsOutTotal, + duration_in_millis: durationInMillis, + millis_per_event: durationInMillis / eventsTotal, + ...inputStats, + ...processorStats, + ...eventsProcessedStats + }; +} + +/** + * The UI needs a list of all vertices for the requested pipeline version, with each vertex in the list having its timeseries metrics associated with it. The + * stateDocument object provides the list of vertices while the statsAggregation object provides the timeseries metrics for each of these vertices. + * This function stitches the two together and returns the modified stateDocument object. + * + * @param {Object} stateDocument + * @param {Object} vertexStatsAggregation + * @param {Object} First and last seen timestamps for pipeline version we're getting data for + * @param {Integer} timeseriesIntervalInSeconds The size of each timeseries bucket, in seconds + */ +export function _enrichVertexStateWithStatsAggregation(stateDocument, vertexStatsAggregation, vertexId, timeseriesIntervalInSeconds) { + const logstashState = stateDocument.logstash_state; + const vertices = logstashState.pipeline.representation.graph.vertices; + + // First, filter out the vertex we care about + const vertex = vertices.find(v => v.id === vertexId); + vertex.stats = {}; + + // Next, iterate over timeseries metrics and attach them to vertex + const timeSeriesBuckets = vertexStatsAggregation.aggregations.timeseries.buckets; + timeSeriesBuckets.forEach(timeSeriesBucket => { + // each bucket calculates stats for total pipeline CPU time for the associated timeseries + const totalDurationStats = timeSeriesBucket.pipelines.scoped.total_processor_duration_stats; + const totalProcessorsDurationInMillis = totalDurationStats.max - totalDurationStats.min; + + const timestamp = timeSeriesBucket.key; + + const vertexStatsBucket = timeSeriesBucket.pipelines.scoped.vertices.vertex_id; + const vertexStats = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds); + Object.keys(vertexStats).forEach(stat => { + if (!vertex.stats.hasOwnProperty(stat)) { + vertex.stats[stat] = { data: [] }; + } + vertex.stats[stat].data.push([ timestamp, vertexStats[stat] ]); + }); + }); + + return vertex; +} + +export async function getPipelineVertex(req, config, lsIndexPattern, clusterUuid, pipelineId, version, vertexId) { + checkParam(lsIndexPattern, 'lsIndexPattern in getPipeline'); + + const options = { + clusterUuid, + pipelineId, + version, + vertexId + }; + + // Determine metrics' timeseries interval based on version's timespan + const minIntervalSeconds = config.get('xpack.monitoring.min_interval_seconds'); + const timeseriesInterval = calculateTimeseriesInterval(version.firstSeen, version.lastSeen, minIntervalSeconds); + + const [ stateDocument, statsAggregation ] = await Promise.all([ + getPipelineStateDocument(req, lsIndexPattern, options), + getPipelineVertexStatsAggregation(req, lsIndexPattern, timeseriesInterval, options), + ]); + + if (stateDocument === null) { + return boom.notFound(`Pipeline [${pipelineId} @ ${version.hash}] not found in the selected time range for cluster [${clusterUuid}].`); + } + + return _enrichVertexStateWithStatsAggregation(stateDocument, statsAggregation, vertexId, timeseriesInterval); +} diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex_stats_aggregation.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex_stats_aggregation.js new file mode 100644 index 0000000000000..5c80165e74bf4 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex_stats_aggregation.js @@ -0,0 +1,189 @@ +/* + * 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 { createQuery } from '../create_query'; +import { LogstashMetric } from '../metrics'; + +function scalarCounterAggregation(field, fieldPath, ephemeralIdField, maxBucketSize) { + const fullPath = `${fieldPath}.${field}`; + + const byEphemeralIdName = `${field}_temp_by_ephemeral_id`; + const sumName = `${field}_total`; + + const aggs = {}; + + aggs[byEphemeralIdName] = { + terms: { + field: ephemeralIdField, + size: maxBucketSize, + }, + aggs: { + stats: { + stats: { field: fullPath } + }, + difference: { + bucket_script: { + script: 'params.max - params.min', + buckets_path: { + min: 'stats.min', + max: 'stats.max' + } + } + } + } + }; + + aggs[sumName] = { + sum_bucket: { + buckets_path: `${byEphemeralIdName}>difference` + } + }; + + return aggs; +} + + +function createAggsObjectFromAggsList(aggsList) { + return aggsList.reduce((aggsSoFar, agg) => ({ ...aggsSoFar, ...agg }), {}); +} + +function createNestedVertexAgg(vertexId, maxBucketSize) { + const fieldPath = 'logstash_stats.pipelines.vertices'; + const ephemeralIdField = 'logstash_stats.pipelines.vertices.pipeline_ephemeral_id'; + + return { + vertices: { + nested: { path: 'logstash_stats.pipelines.vertices' }, + aggs: { + vertex_id: { + filter: { + term: { + 'logstash_stats.pipelines.vertices.id': vertexId + } + }, + aggs: { + ...scalarCounterAggregation('events_in', fieldPath, ephemeralIdField, maxBucketSize), + ...scalarCounterAggregation('events_out', fieldPath, ephemeralIdField, maxBucketSize), + ...scalarCounterAggregation('duration_in_millis', fieldPath, ephemeralIdField, maxBucketSize), + ...scalarCounterAggregation('queue_push_duration_in_millis', fieldPath, ephemeralIdField, maxBucketSize) + } + } + } + } + }; +} + +function createTotalProcessorDurationStatsAgg() { + return { + total_processor_duration_stats: { + stats: { + field: 'logstash_stats.pipelines.events.duration_in_millis' + } + } + }; +} + +function createScopedAgg(pipelineId, pipelineHash, ...aggsList) { + return { + pipelines: { + nested: { path: 'logstash_stats.pipelines' }, + aggs: { + scoped: { + filter: { + bool: { + filter: [ + { term: { 'logstash_stats.pipelines.id': pipelineId } }, + { term: { 'logstash_stats.pipelines.hash': pipelineHash } } + ] + } + }, + aggs: createAggsObjectFromAggsList(aggsList) + } + } + } + }; +} + +function createTimeSeriesAgg(timeSeriesIntervalInSeconds, ...aggsList) { + return { + timeseries: { + date_histogram: { + field: 'timestamp', + interval: timeSeriesIntervalInSeconds + 's' + }, + aggs: createAggsObjectFromAggsList(aggsList) + } + }; +} + +function fetchPipelineVertexTimeSeriesStats(query, logstashIndexPattern, pipelineId, version, vertexId, + timeSeriesIntervalInSeconds, maxBucketSize, callWithRequest, req) { + const aggs = { + ...createTimeSeriesAgg(timeSeriesIntervalInSeconds, + createScopedAgg(pipelineId, version.hash, + createNestedVertexAgg(vertexId, maxBucketSize), + createTotalProcessorDurationStatsAgg() + ) + ) + }; + + const params = { + index: logstashIndexPattern, + size: 0, + ignoreUnavailable: true, + filterPath: [ + 'aggregations.timeseries.buckets.key', + 'aggregations.timeseries.buckets.pipelines.scoped.vertices.vertex_id.events_in_total', + 'aggregations.timeseries.buckets.pipelines.scoped.vertices.vertex_id.events_out_total', + 'aggregations.timeseries.buckets.pipelines.scoped.vertices.vertex_id.duration_in_millis_total', + 'aggregations.timeseries.buckets.pipelines.scoped.vertices.vertex_id.queue_push_duration_in_millis_total', + 'aggregations.timeseries.buckets.pipelines.scoped.total_processor_duration_stats' + ], + body: { + query: query, + aggs + } + }; + + return callWithRequest(req, 'search', params); +} + +export function getPipelineVertexStatsAggregation(req, logstashIndexPattern, timeSeriesIntervalInSeconds, + { clusterUuid, start, end, pipelineId, version, vertexId }) { + const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); + const filters = [ + { + nested: { + path: 'logstash_stats.pipelines', + query: { + bool: { + must: [ + { term: { 'logstash_stats.pipelines.hash': version.hash } }, + { term: { 'logstash_stats.pipelines.id': pipelineId } }, + ] + } + } + } + } + ]; + + start = version.firstSeen; + end = version.lastSeen; + + const query = createQuery({ + type: 'logstash_stats', + start, + end, + metric: LogstashMetric.getMetricFields(), + clusterUuid, + filters + }); + + const config = req.server.config(); + + return fetchPipelineVertexTimeSeriesStats(query, logstashIndexPattern, pipelineId, version, vertexId, + timeSeriesIntervalInSeconds, config.get('xpack.monitoring.max_bucket_size'), callWithRequest, req); +} diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js index 433c48f02b3ea..fdd9342cf9eae 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js @@ -6,10 +6,18 @@ import Joi from 'joi'; import { handleError } from '../../../../lib/errors'; +import { getPipelineVersions } from '../../../../lib/logstash/get_pipeline_versions'; import { getPipeline } from '../../../../lib/logstash/get_pipeline'; +import { getPipelineVertex } from '../../../../lib/logstash/get_pipeline_vertex'; import { prefixIndexPattern } from '../../../../lib/ccs_utils'; import { INDEX_PATTERN_LOGSTASH } from '../../../../../common/constants'; +function getPipelineVersion(versions, pipelineHash) { + return pipelineHash + ? versions.find(({ hash }) => hash === pipelineHash) + : versions[0]; +} + /* * Logstash Pipeline route. */ @@ -34,22 +42,46 @@ export function logstashPipelineRoute(server) { pipelineHash: Joi.string().optional() }), payload: Joi.object({ - ccs: Joi.string().optional() + ccs: Joi.string().optional(), + detailVertexId: Joi.string().optional() }) } }, - handler: (req) => { + handler: async (req) => { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; + const detailVertexId = req.payload.detailVertexId; const lsIndexPattern = prefixIndexPattern(config, INDEX_PATTERN_LOGSTASH, ccs); const pipelineId = req.params.pipelineId; // Optional params default to empty string, set to null to be more explicit. const pipelineHash = req.params.pipelineHash || null; - return getPipeline(req, config, lsIndexPattern, clusterUuid, pipelineId, pipelineHash) - .catch(err => handleError(err, req)); + // Figure out which version of the pipeline we want to show + let versions; + try { + versions = await getPipelineVersions(req, config, lsIndexPattern, clusterUuid, pipelineId); + } catch (err) { + return handleError(err, req); + } + const version = getPipelineVersion(versions, pipelineHash); + + const promises = [ getPipeline(req, config, lsIndexPattern, clusterUuid, pipelineId, version) ]; + if (detailVertexId) { + promises.push(getPipelineVertex(req, config, lsIndexPattern, clusterUuid, pipelineId, version, detailVertexId)); + } + + try { + const [ pipeline, vertex ] = await Promise.all(promises); + return { + versions, + pipeline, + vertex + }; + } catch (err) { + return handleError(err, req); + } } }); } From e247609e8b525e0b6ea200b6e65ecb5e00be6ab9 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 26 Mar 2019 10:00:53 -0600 Subject: [PATCH 33/96] [Maps] split settings into layer and source panels (#33788) * [Maps] split settings into layer and source panels * fix SCSS import --- .../__snapshots__/view.test.js.snap | 7 +-- .../public/components/layer_panel/_index.scss | 2 +- .../__snapshots__/layer_errors.test.js.snap | 22 ++++++++ .../layer_panel/layer_errors/index.js | 18 ++++++ .../layer_panel/layer_errors/layer_errors.js | 37 +++++++++++++ .../layer_errors/layer_errors.test.js | 39 +++++++++++++ .../_layer_settings.scss} | 0 .../index.js | 8 +-- .../layer_settings.js} | 42 ++------------ .../source_settings.test.js.snap | 39 +++++++++++++ .../layer_panel/source_settings/index.js | 25 +++++++++ .../source_settings/source_settings.js | 55 +++++++++++++++++++ .../source_settings/source_settings.test.js | 42 ++++++++++++++ .../public/components/layer_panel/view.js | 15 ++++- .../components/layer_panel/view.test.js | 20 +++++-- 15 files changed, 317 insertions(+), 54 deletions(-) create mode 100644 x-pack/plugins/maps/public/components/layer_panel/layer_errors/__snapshots__/layer_errors.test.js.snap create mode 100644 x-pack/plugins/maps/public/components/layer_panel/layer_errors/index.js create mode 100644 x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.js create mode 100644 x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.test.js rename x-pack/plugins/maps/public/components/layer_panel/{settings_panel/_settings_panel.scss => layer_settings/_layer_settings.scss} (100%) rename x-pack/plugins/maps/public/components/layer_panel/{settings_panel => layer_settings}/index.js (79%) rename x-pack/plugins/maps/public/components/layer_panel/{settings_panel/settings_panel.js => layer_settings/layer_settings.js} (78%) create mode 100644 x-pack/plugins/maps/public/components/layer_panel/source_settings/__snapshots__/source_settings.test.js.snap create mode 100644 x-pack/plugins/maps/public/components/layer_panel/source_settings/index.js create mode 100644 x-pack/plugins/maps/public/components/layer_panel/source_settings/source_settings.js create mode 100644 x-pack/plugins/maps/public/components/layer_panel/source_settings/source_settings.test.js diff --git a/x-pack/plugins/maps/public/components/layer_panel/__snapshots__/view.test.js.snap b/x-pack/plugins/maps/public/components/layer_panel/__snapshots__/view.test.js.snap index 1774258d99834..d260aebd67d5f 100644 --- a/x-pack/plugins/maps/public/components/layer_panel/__snapshots__/view.test.js.snap +++ b/x-pack/plugins/maps/public/components/layer_panel/__snapshots__/view.test.js.snap @@ -82,10 +82,9 @@ exports[`LayerPanel is rendered 1`] = ` - - + + + + +

    + simulated layer error +

    +
    + + +`; + +exports[`should render nothing when layer has no errors 1`] = `""`; diff --git a/x-pack/plugins/maps/public/components/layer_panel/layer_errors/index.js b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/index.js new file mode 100644 index 0000000000000..21ff81e32f607 --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/index.js @@ -0,0 +1,18 @@ +/* + * 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 { connect } from 'react-redux'; +import { LayerErrors } from './layer_errors'; +import { getSelectedLayer } from '../../../selectors/map_selectors'; + +function mapStateToProps(state = {}) { + return { + layer: getSelectedLayer(state) + }; +} + +const connectedLayerErrors = connect(mapStateToProps, null)(LayerErrors); +export { connectedLayerErrors as LayerErrors }; diff --git a/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.js b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.js new file mode 100644 index 0000000000000..755a1ed39ff8d --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.js @@ -0,0 +1,37 @@ +/* + * 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, { Fragment } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiCallOut, + EuiSpacer, +} from '@elastic/eui'; + +export function LayerErrors({ layer }) { + + if (!layer.hasErrors()) { + return null; + } + + return ( + + +

    + {layer.getErrors()} +

    +
    + +
    + ); +} diff --git a/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.test.js b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.test.js new file mode 100644 index 0000000000000..fd2b8540bee16 --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.test.js @@ -0,0 +1,39 @@ +/* + * 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 { shallow } from 'enzyme'; + +import { LayerErrors } from './layer_errors'; + +test('Should render errors when layer has errors', () => { + const mockLayer = { + hasErrors: () => { return true; }, + getErrors: () => { return 'simulated layer error'; } + }; + const component = shallow( + + ); + + expect(component) + .toMatchSnapshot(); +}); + +test('should render nothing when layer has no errors', () => { + const mockLayer = { + hasErrors: () => { return false; }, + }; + const component = shallow( + + ); + + expect(component) + .toMatchSnapshot(); +}); diff --git a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/_settings_panel.scss b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/_layer_settings.scss similarity index 100% rename from x-pack/plugins/maps/public/components/layer_panel/settings_panel/_settings_panel.scss rename to x-pack/plugins/maps/public/components/layer_panel/layer_settings/_layer_settings.scss diff --git a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/index.js b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/index.js similarity index 79% rename from x-pack/plugins/maps/public/components/layer_panel/settings_panel/index.js rename to x-pack/plugins/maps/public/components/layer_panel/layer_settings/index.js index b82e2e0e62a27..e0a1275155211 100644 --- a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/index.js +++ b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/index.js @@ -5,14 +5,13 @@ */ import { connect } from 'react-redux'; -import { SettingsPanel } from './settings_panel'; +import { LayerSettings } from './layer_settings'; import { getSelectedLayer } from '../../../selectors/map_selectors'; import { updateLayerLabel, updateLayerMaxZoom, updateLayerMinZoom, updateLayerAlpha, - updateSourceProp, } from '../../../actions/store_actions'; function mapStateToProps(state = {}) { @@ -33,9 +32,8 @@ function mapDispatchToProps(dispatch) { updateMinZoom: (id, minZoom) => dispatch(updateLayerMinZoom(id, minZoom)), updateMaxZoom: (id, maxZoom) => dispatch(updateLayerMaxZoom(id, maxZoom)), updateAlpha: (id, alpha) => dispatch(updateLayerAlpha(id, alpha)), - updateSourceProp: (id, propName, value) => dispatch(updateSourceProp(id, propName, value)), }; } -const connectedSettingsPanel = connect(mapStateToProps, mapDispatchToProps)(SettingsPanel); -export { connectedSettingsPanel as SettingsPanel }; +const connectedLayerSettings = connect(mapStateToProps, mapDispatchToProps)(LayerSettings); +export { connectedLayerSettings as LayerSettings }; diff --git a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/settings_panel.js b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/layer_settings.js similarity index 78% rename from x-pack/plugins/maps/public/components/layer_panel/settings_panel/settings_panel.js rename to x-pack/plugins/maps/public/components/layer_panel/layer_settings/layer_settings.js index 61563f4375af0..0a01498986e90 100644 --- a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/settings_panel.js +++ b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/layer_settings.js @@ -14,7 +14,6 @@ import { EuiFormRow, EuiFieldText, EuiSpacer, - EuiCallOut } from '@elastic/eui'; import { ValidatedRange } from '../../../shared/components/validated_range'; @@ -25,7 +24,7 @@ import { ValidatedDualRange } from 'ui/validated_range'; const MIN_ZOOM = 0; const MAX_ZOOM = 24; -export function SettingsPanel(props) { +export function LayerSettings(props) { const onLabelChange = (event) => { const label = event.target.value; @@ -41,34 +40,6 @@ export function SettingsPanel(props) { props.updateAlpha(props.layerId, alpha); }; - const onSourceChange = ({ propName, value }) => { - props.updateSourceProp(props.layerId, propName, value); - }; - - const renderLayerErrors = () => { - if (!props.layer.hasErrors()) { - return null; - } - - return ( - - -

    - {props.layer.getErrors()} -

    -
    - -
    - ); - }; - const renderZoomSliders = () => { return ( - - {renderLayerErrors()} -
    @@ -170,9 +138,9 @@ export function SettingsPanel(props) { {renderZoomSliders()} {renderAlphaSlider()} - - {props.layer.renderSourceSettingsEditor({ onChange: onSourceChange })}
    + + ); } diff --git a/x-pack/plugins/maps/public/components/layer_panel/source_settings/__snapshots__/source_settings.test.js.snap b/x-pack/plugins/maps/public/components/layer_panel/source_settings/__snapshots__/source_settings.test.js.snap new file mode 100644 index 0000000000000..48af4ec7286cb --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/source_settings/__snapshots__/source_settings.test.js.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Should render source settings editor 1`] = ` + + + + + +
    + +
    +
    +
    +
    + +
    + mockSourceEditor +
    +
    + +
    +`; + +exports[`should render nothing when source has no editor 1`] = `""`; diff --git a/x-pack/plugins/maps/public/components/layer_panel/source_settings/index.js b/x-pack/plugins/maps/public/components/layer_panel/source_settings/index.js new file mode 100644 index 0000000000000..04885c5b5c485 --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/source_settings/index.js @@ -0,0 +1,25 @@ +/* + * 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 { connect } from 'react-redux'; +import { SourceSettings } from './source_settings'; +import { getSelectedLayer } from '../../../selectors/map_selectors'; +import { updateSourceProp } from '../../../actions/store_actions'; + +function mapStateToProps(state = {}) { + return { + layer: getSelectedLayer(state) + }; +} + +function mapDispatchToProps(dispatch) { + return { + updateSourceProp: (id, propName, value) => dispatch(updateSourceProp(id, propName, value)), + }; +} + +const connectedSourceSettings = connect(mapStateToProps, mapDispatchToProps)(SourceSettings); +export { connectedSourceSettings as SourceSettings }; diff --git a/x-pack/plugins/maps/public/components/layer_panel/source_settings/source_settings.js b/x-pack/plugins/maps/public/components/layer_panel/source_settings/source_settings.js new file mode 100644 index 0000000000000..6a1a75327427a --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/source_settings/source_settings.js @@ -0,0 +1,55 @@ +/* + * 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, { Fragment } from 'react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiPanel, + EuiSpacer, +} from '@elastic/eui'; + +import { FormattedMessage } from '@kbn/i18n/react'; + +export function SourceSettings({ layer, updateSourceProp }) { + + const onSourceChange = ({ propName, value }) => { + updateSourceProp(layer.getId(), propName, value); + }; + + const sourceSettingsEditor = layer.renderSourceSettingsEditor({ onChange: onSourceChange }); + + if (!sourceSettingsEditor) { + return null; + } + + return ( + + + + + +
    + +
    +
    +
    +
    + + + + {sourceSettingsEditor} +
    + + +
    + ); +} diff --git a/x-pack/plugins/maps/public/components/layer_panel/source_settings/source_settings.test.js b/x-pack/plugins/maps/public/components/layer_panel/source_settings/source_settings.test.js new file mode 100644 index 0000000000000..090d30054ba81 --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/source_settings/source_settings.test.js @@ -0,0 +1,42 @@ +/* + * 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 { shallow } from 'enzyme'; + +import { SourceSettings } from './source_settings'; + +test('Should render source settings editor', () => { + const mockLayer = { + renderSourceSettingsEditor: () => { + return (
    mockSourceEditor
    ); + }, + }; + const component = shallow( + + ); + + expect(component) + .toMatchSnapshot(); +}); + +test('should render nothing when source has no editor', () => { + const mockLayer = { + renderSourceSettingsEditor: () => { + return null; + }, + }; + const component = shallow( + + ); + + expect(component) + .toMatchSnapshot(); +}); diff --git a/x-pack/plugins/maps/public/components/layer_panel/view.js b/x-pack/plugins/maps/public/components/layer_panel/view.js index 36e4ac6f484f6..20a5a2669484b 100644 --- a/x-pack/plugins/maps/public/components/layer_panel/view.js +++ b/x-pack/plugins/maps/public/components/layer_panel/view.js @@ -9,7 +9,9 @@ import React, { Fragment } from 'react'; import { StyleTabs } from './style_tabs'; import { JoinEditor } from './join_editor'; import { FlyoutFooter } from './flyout_footer'; -import { SettingsPanel } from './settings_panel'; +import { LayerErrors } from './layer_errors'; +import { LayerSettings } from './layer_settings'; +import { SourceSettings } from './source_settings'; import { EuiButtonIcon, EuiFlexItem, @@ -175,10 +177,17 @@ export class LayerPanel extends React.Component { - - + + + + + + + {this._renderJoinSection()} + + diff --git a/x-pack/plugins/maps/public/components/layer_panel/view.test.js b/x-pack/plugins/maps/public/components/layer_panel/view.test.js index 200345bf92b74..6a5208ce13c0b 100644 --- a/x-pack/plugins/maps/public/components/layer_panel/view.test.js +++ b/x-pack/plugins/maps/public/components/layer_panel/view.test.js @@ -22,9 +22,21 @@ jest.mock('./flyout_footer', () => ({ } })); -jest.mock('./settings_panel', () => ({ - SettingsPanel: () => { - return (
    mockSettingsPanel
    ); +jest.mock('./layer_errors', () => ({ + LayerErrors: () => { + return (
    mockLayerErrors
    ); + } +})); + +jest.mock('./layer_settings', () => ({ + LayerSettings: () => { + return (
    mockLayerSettings
    ); + } +})); + +jest.mock('./source_settings', () => ({ + SourceSettings: () => { + return (
    mockSourceSettings
    ); } })); @@ -42,7 +54,7 @@ const mockLayer = { ]; }, isJoinable: () => { return true; }, - getLayerTypeIconName: () => { return 'vector'; } + getLayerTypeIconName: () => { return 'vector'; }, }; const defaultProps = { From 369f0f2922ffb3cb5243dffebe8e4e209ac579e3 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Tue, 26 Mar 2019 11:20:41 -0500 Subject: [PATCH 34/96] [env] exit if starting as root (#21563) * [env] exit if starting as root * fix windows * s/--allow-root --- src/setup_node_env/index.js | 1 + src/setup_node_env/root/force.js | 25 ++++++++++++++++ src/setup_node_env/root/force.test.js | 39 +++++++++++++++++++++++++ src/setup_node_env/root/index.js | 28 ++++++++++++++++++ src/setup_node_env/root/is_root.js | 22 ++++++++++++++ src/setup_node_env/root/is_root.test.js | 32 ++++++++++++++++++++ 6 files changed, 147 insertions(+) create mode 100644 src/setup_node_env/root/force.js create mode 100644 src/setup_node_env/root/force.test.js create mode 100644 src/setup_node_env/root/index.js create mode 100644 src/setup_node_env/root/is_root.js create mode 100644 src/setup_node_env/root/is_root.test.js diff --git a/src/setup_node_env/index.js b/src/setup_node_env/index.js index 6592fa9fd2424..a3fe8d938ba2b 100644 --- a/src/setup_node_env/index.js +++ b/src/setup_node_env/index.js @@ -17,5 +17,6 @@ * under the License. */ +require('./root'); require('./node_version_validator'); require('./babel_register'); diff --git a/src/setup_node_env/root/force.js b/src/setup_node_env/root/force.js new file mode 100644 index 0000000000000..5c5370aec6b15 --- /dev/null +++ b/src/setup_node_env/root/force.js @@ -0,0 +1,25 @@ +/* + * 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. + */ + +module.exports = function (argv) { + var rootIndex = argv.indexOf('--allow-root'); + var force = rootIndex >= 0; + if (force) argv.splice(rootIndex, 1); + return force; +}; diff --git a/src/setup_node_env/root/force.test.js b/src/setup_node_env/root/force.test.js new file mode 100644 index 0000000000000..df013349e57ed --- /dev/null +++ b/src/setup_node_env/root/force.test.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +var forceRoot = require('./force'); + +describe('forceRoot', function () { + + it('with flag', function () { + expect(forceRoot(['--allow-root'])).toBeTruthy(); + }); + + it('without flag', function () { + expect(forceRoot(['--foo'])).toBeFalsy(); + + }); + + test('remove argument', function () { + var args = ['--allow-root', 'foo']; + forceRoot(args); + expect(args.includes('--allow-root')).toBeFalsy(); + }); + +}); diff --git a/src/setup_node_env/root/index.js b/src/setup_node_env/root/index.js new file mode 100644 index 0000000000000..5a402dfcb4eeb --- /dev/null +++ b/src/setup_node_env/root/index.js @@ -0,0 +1,28 @@ +/* + * 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. + */ + +var force = require('./force')(process.argv); + +var uid = process.getuid && process.getuid(); +var isRoot = require('./is_root')(uid); + +if(isRoot && !force) { + console.error('Kibana should not be run as root. Use --allow-root to continue.'); + process.exit(1); +} diff --git a/src/setup_node_env/root/is_root.js b/src/setup_node_env/root/is_root.js new file mode 100644 index 0000000000000..e2eaaf6af5154 --- /dev/null +++ b/src/setup_node_env/root/is_root.js @@ -0,0 +1,22 @@ +/* + * 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. + */ + +module.exports = function (uid) { + return uid === 0; +}; diff --git a/src/setup_node_env/root/is_root.test.js b/src/setup_node_env/root/is_root.test.js new file mode 100644 index 0000000000000..a976299cd5d5b --- /dev/null +++ b/src/setup_node_env/root/is_root.test.js @@ -0,0 +1,32 @@ +/* + * 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. + */ + +var isRoot = require('./is_root'); + + +describe('isRoot', function () { + + test('0 is root', function () { + expect(isRoot(0)).toBeTruthy(); + }); + + test('not 0 is not root', function () { + expect(isRoot(5)).toBeFalsy(); + }); +}); From f5010cc8e6122eb89a507e34e0d89c28febe7728 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Tue, 26 Mar 2019 12:31:10 -0400 Subject: [PATCH 35/96] Typescript sample panel action (#33602) * Typescript sample panel action * Update EUI version to match main cabana version * update yarn.lock * add back typings include * use correct relative path --- package.json | 3 +-- src/dev/typescript/projects.ts | 3 +++ .../embeddable/context_menu_actions/index.ts | 1 + .../{index.js => index.ts} | 16 +++++++----- .../kbn_tp_sample_panel_action/package.json | 13 ++++++++-- ...anel_action.js => sample_panel_action.tsx} | 10 ++++--- ...ple_panel_link.js => sample_panel_link.ts} | 10 +++---- .../kbn_tp_sample_panel_action/tsconfig.json | 14 ++++++++++ test/scripts/jenkins_ci_group.sh | 6 ++++- test/tsconfig.json | 6 ++++- yarn.lock | 26 +++++++++++++++++++ 11 files changed, 87 insertions(+), 21 deletions(-) rename test/plugin_functional/plugins/kbn_tp_sample_panel_action/{index.js => index.ts} (75%) rename test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/{sample_panel_action.js => sample_panel_action.tsx} (93%) rename test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/{sample_panel_link.js => sample_panel_link.ts} (90%) create mode 100644 test/plugin_functional/plugins/kbn_tp_sample_panel_action/tsconfig.json diff --git a/package.json b/package.json index 30bd3f9d52897..43f6c6704c600 100644 --- a/package.json +++ b/package.json @@ -90,8 +90,7 @@ "**/@types/*/**", "**/grunt-*", "**/grunt-*/**", - "x-pack/typescript", - "kbn_tp_*/**" + "x-pack/typescript" ] }, "dependencies": { diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index 540441ab6b8de..7ef3419751be5 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -35,6 +35,9 @@ export const PROJECTS = [ ...glob .sync('packages/*/tsconfig.json', { cwd: REPO_ROOT }) .map(path => new Project(resolve(REPO_ROOT, path))), + ...glob + .sync('test/plugin_functional/plugins/*/tsconfig.json', { cwd: REPO_ROOT }) + .map(path => new Project(resolve(REPO_ROOT, path))), ]; export function filterProjectsByFlag(projectFlag?: string) { diff --git a/src/legacy/ui/public/embeddable/context_menu_actions/index.ts b/src/legacy/ui/public/embeddable/context_menu_actions/index.ts index 152fdee9f7fff..d43f1d16aefd1 100644 --- a/src/legacy/ui/public/embeddable/context_menu_actions/index.ts +++ b/src/legacy/ui/public/embeddable/context_menu_actions/index.ts @@ -21,3 +21,4 @@ export { ContextMenuPanel } from './context_menu_panel'; export { ContextMenuAction } from './context_menu_action'; export { ContextMenuActionsRegistryProvider } from './context_menu_actions_registry'; export { buildEuiContextMenuPanels } from './build_eui_context_menu_panels'; +export { PanelActionAPI } from './types'; diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.js b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.ts similarity index 75% rename from test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.js rename to test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.ts index c4aaaa857cecd..dd069010e0742 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.js +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.ts @@ -17,8 +17,15 @@ * under the License. */ -function samplePanelAction(kibana) { +import { resolve } from 'path'; + +// TODO: use something better once https://github.com/elastic/kibana/issues/26555 is +// figured out. +type KibanaPlugin = any; + +function samplePanelAction(kibana: KibanaPlugin) { return new kibana.Plugin({ + publicDir: resolve(__dirname, './public'), uiExports: { contextMenuActions: [ 'plugins/kbn_tp_sample_panel_action/sample_panel_action', @@ -28,9 +35,6 @@ function samplePanelAction(kibana) { }); } -module.exports = function (kibana) { - return [ - samplePanelAction(kibana), - ]; +module.exports = (kibana: KibanaPlugin) => { + return [samplePanelAction(kibana)]; }; - diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json index ae68ac4f5c543..462f5448d7cff 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json @@ -1,13 +1,22 @@ { "name": "kbn_tp_sample_panel_action", "version": "1.0.0", + "main":"target/test/plugin_functional/plugins/kbn_tp_sample_panel_action", "kibana": { "version": "kibana", "templateVersion": "1.0.0" }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.4.0", + "@elastic/eui": "9.4.2", "react": "^16.8.0" + }, + "scripts": { + "kbn": "node ../../../../scripts/kbn.js", + "build": "rm -rf './target' && tsc" + }, + "devDependencies": { + "@kbn/plugin-helpers" : "9.0.2", + "typescript": "^3.3.3333" } -} +} \ No newline at end of file diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.js b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx similarity index 93% rename from test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.js rename to test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx index 1310ff027e35e..41c867b5526d5 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.js +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx @@ -23,6 +23,7 @@ import { openFlyout } from 'ui/flyout'; import { ContextMenuAction, ContextMenuActionsRegistryProvider, + PanelActionAPI, } from 'ui/embeddable'; class SamplePanelAction extends ContextMenuAction { @@ -33,7 +34,10 @@ class SamplePanelAction extends ContextMenuAction { parentPanelId: 'mainMenu', }); } - onClick({ embeddable }) { + public onClick = ({ embeddable }: PanelActionAPI) => { + if (!embeddable) { + return; + } openFlyout( @@ -47,9 +51,9 @@ class SamplePanelAction extends ContextMenuAction { , { 'data-test-subj': 'samplePanelActionFlyout', - }, + } ); - } + }; } ContextMenuActionsRegistryProvider.register(() => new SamplePanelAction()); diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.js b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts similarity index 90% rename from test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.js rename to test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts index 0b99b7eadb3c7..7092c783125d9 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.js +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts @@ -16,10 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { - ContextMenuAction, - ContextMenuActionsRegistryProvider, -} from 'ui/embeddable'; +import { ContextMenuAction, ContextMenuActionsRegistryProvider } from 'ui/embeddable'; class SamplePanelLink extends ContextMenuAction { constructor() { @@ -29,9 +26,10 @@ class SamplePanelLink extends ContextMenuAction { parentPanelId: 'mainMenu', }); } - getHref() { + + public getHref = () => { return 'https://example.com/kibana/test'; - } + }; } ContextMenuActionsRegistryProvider.register(() => new SamplePanelLink()); diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/tsconfig.json new file mode 100644 index 0000000000000..aba7203377aff --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "../../../../typings/**/*", + ], + "exclude": [] +} \ No newline at end of file diff --git a/test/scripts/jenkins_ci_group.sh b/test/scripts/jenkins_ci_group.sh index c9eec36cdc743..a4bc597316dcb 100755 --- a/test/scripts/jenkins_ci_group.sh +++ b/test/scripts/jenkins_ci_group.sh @@ -22,6 +22,10 @@ export TEST_BROWSER_HEADLESS=1 "$(FORCE_COLOR=0 yarn bin)/grunt" "run:functionalTests_ciGroup${CI_GROUP}"; if [ "$CI_GROUP" == "1" ]; then - "$(FORCE_COLOR=0 yarn bin)/grunt" run:pluginFunctionalTestsRelease; + # build kbn_tp_sample_panel_action + cd test/plugin_functional/plugins/kbn_tp_sample_panel_action; + yarn build; + cd -; + "$(FORCE_COLOR=0 yarn bin)/grunt" run:pluginFunctionalTestsRelease --from=source; "$(FORCE_COLOR=0 yarn bin)/grunt" run:interpreterFunctionalTestsRelease; fi diff --git a/test/tsconfig.json b/test/tsconfig.json index 5df729fbde21b..d620d28f3d1de 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -7,6 +7,10 @@ ] }, "include": [ - "**/*.ts" + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "plugin_functional/plugins/**/*" ] } diff --git a/yarn.lock b/yarn.lock index 1bd2096868381..e15a2219367b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -822,6 +822,32 @@ tabbable "^1.1.0" uuid "^3.1.0" +"@elastic/eui@9.4.2": + version "9.4.2" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-9.4.2.tgz#530ec18f9b1cb3972824a707cc0cb3005c6c5028" + integrity sha512-2fH+WiYYq1tPn5mEvg5NR5b9TjVYY0cM26HPERMRMZyAenGFQtjhansO8qFlTl/MAYz5GsQ7ejgdtzu095opdw== + dependencies: + "@types/lodash" "^4.14.116" + "@types/numeral" "^0.0.25" + classnames "^2.2.5" + core-js "^2.5.1" + highlight.js "^9.12.0" + html "^1.0.0" + keymirror "^0.1.1" + lodash "^4.17.11" + numeral "^2.0.6" + prop-types "^15.6.0" + react-ace "^5.5.0" + react-color "^2.13.8" + react-focus-lock "^1.17.7" + react-input-autosize "^2.2.1" + react-is "~16.3.0" + react-virtualized "^9.18.5" + react-vis "1.10.2" + resize-observer-polyfill "^1.5.0" + tabbable "^1.1.0" + uuid "^3.1.0" + "@elastic/eui@9.5.0": version "9.5.0" resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-9.5.0.tgz#233b4722b0cd2506793472ec1c6b97640a365229" From 57c7572367d658d2ee3707ba6925ac05aac3fdb4 Mon Sep 17 00:00:00 2001 From: Philipp B Date: Tue, 26 Mar 2019 19:40:58 +0300 Subject: [PATCH 36/96] Home page "recent links" should communicate saved object type #21896 (#33694) * adds object type for screen order * adds object type for pointer hovering * Update src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx Co-Authored-By: rockfield --- .../header_global_nav/components/header.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx b/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx index d8426805f57ba..d8aec7997fdbf 100644 --- a/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx +++ b/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx @@ -54,6 +54,7 @@ import { HeaderBreadcrumbs } from './header_breadcrumbs'; import { HeaderHelpMenu } from './header_help_menu'; import { HeaderNavControls } from './header_nav_controls'; +import { i18n } from '@kbn/i18n'; import { InjectedIntl, injectI18n } from '@kbn/i18n/react'; import chrome, { NavLink } from 'ui/chrome'; import { HelpExtension } from 'ui/chrome'; @@ -88,10 +89,23 @@ function extendRecentlyAccessedHistoryItem( const href = relativeToAbsolute(chrome.addBasePath(recentlyAccessed.link)); const navLink = navLinks.find(nl => href.startsWith(nl.subUrlBase)); + let titleAndAriaLabel = recentlyAccessed.label; + if (navLink) { + const objectTypeForAriaAppendix = navLink.title; + titleAndAriaLabel = i18n.translate('common.ui.recentLinks.linkItem.screenReaderLabel', { + defaultMessage: '{recentlyAccessedItemLinklabel}, type: {pageType}', + values: { + recentlyAccessedItemLinklabel: recentlyAccessed.label, + pageType: objectTypeForAriaAppendix, + }, + }); + } + return { ...recentlyAccessed, href, euiIconType: navLink ? navLink.euiIconType : undefined, + title: titleAndAriaLabel, }; } @@ -248,9 +262,8 @@ class HeaderUI extends Component { }), listItems: recentlyAccessed.map(item => ({ label: truncateRecentItemLabel(item.label), - // TODO: Add what type of app/saved object to title attr - title: `${item.label}`, - 'aria-label': item.label, + title: item.title, + 'aria-label': item.title, href: item.href, iconType: item.euiIconType, })), From 5ad1ee5edb1bfced716ad5223bddd07b9771056a Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 26 Mar 2019 12:18:01 -0700 Subject: [PATCH 37/96] Update advanced setting description. Closes #30753 --- src/legacy/core_plugins/kibana/ui_setting_defaults.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/kibana/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/ui_setting_defaults.js index de8fdd9dabdb5..55cdc3e38e7f3 100644 --- a/src/legacy/core_plugins/kibana/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/ui_setting_defaults.js @@ -323,8 +323,8 @@ export function getUiSettingDefaults() { description: i18n.translate('kbn.advancedSettings.courier.ignoreFilterText', { defaultMessage: 'This configuration enhances support for dashboards containing visualizations accessing dissimilar indexes. ' + - 'When set to false, all filters are applied to all visualizations. ' + - 'When set to true, filter(s) will be ignored for a visualization ' + + 'When disabled, all filters are applied to all visualizations. ' + + 'When enabled, filter(s) will be ignored for a visualization ' + `when the visualization's index does not contain the filtering field.`, }), category: ['search'], From e24cef3f78129a4f6271f62790d75315fd7314fa Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Tue, 26 Mar 2019 14:45:35 -0500 Subject: [PATCH 38/96] Docs/gettingstarted (#32145) (#32218) * Docs/gettingstarted (#32145) * [docs/getting started] remove types * update urls * one primary shard * Update docs/getting-started/tutorial-load-dataset.asciidoc Co-Authored-By: jbudz * dedupe * Update tutorial-load-dataset.asciidoc --- .../tutorial-load-dataset.asciidoc | 74 +++++++++---------- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/docs/getting-started/tutorial-load-dataset.asciidoc b/docs/getting-started/tutorial-load-dataset.asciidoc index d23d50baed662..c7c12199633ac 100644 --- a/docs/getting-started/tutorial-load-dataset.asciidoc +++ b/docs/getting-started/tutorial-load-dataset.asciidoc @@ -3,12 +3,16 @@ This tutorial requires three data sets: -* The complete works of William Shakespeare, suitably parsed into fields. Download - https://download.elastic.co/demos/kibana/gettingstarted/shakespeare_6.0.json[`shakespeare.json`]. -* A set of fictitious accounts with randomly generated data. Download - https://download.elastic.co/demos/kibana/gettingstarted/accounts.zip[`accounts.zip`]. -* A set of randomly generated log files. Download - https://download.elastic.co/demos/kibana/gettingstarted/logs.jsonl.gz[`logs.jsonl.gz`]. +* The complete works of William Shakespeare, suitably parsed into fields +* A set of fictitious accounts with randomly generated data +* A set of randomly generated log files + +Create a new working directory where you want to download the files. From that directory, run the following commands: + +[source,shell] +curl -O https://download.elastic.co/demos/kibana/gettingstarted/8.x/shakespeare.json +curl -O https://download.elastic.co/demos/kibana/gettingstarted/8.x/accounts.zip +curl -O https://download.elastic.co/demos/kibana/gettingstarted/8.x/logs.jsonl.gz Two of the data sets are compressed. To extract the files, use these commands: @@ -73,16 +77,14 @@ In Kibana *Dev Tools > Console*, set up a mapping for the Shakespeare data set: [source,js] PUT /shakespeare { - "mappings": { - "doc": { - "properties": { + "mappings": { + "properties": { "speaker": {"type": "keyword"}, "play_name": {"type": "keyword"}, "line_id": {"type": "integer"}, "speech_number": {"type": "integer"} - } + } } - } } //CONSOLE @@ -100,13 +102,11 @@ as geographic locations by applying the `geo_point` type. PUT /logstash-2015.05.18 { "mappings": { - "log": { - "properties": { - "geo": { - "properties": { - "coordinates": { - "type": "geo_point" - } + "properties": { + "geo": { + "properties": { + "coordinates": { + "type": "geo_point" } } } @@ -120,13 +120,11 @@ PUT /logstash-2015.05.18 PUT /logstash-2015.05.19 { "mappings": { - "log": { - "properties": { - "geo": { - "properties": { - "coordinates": { - "type": "geo_point" - } + "properties": { + "geo": { + "properties": { + "coordinates": { + "type": "geo_point" } } } @@ -140,13 +138,11 @@ PUT /logstash-2015.05.19 PUT /logstash-2015.05.20 { "mappings": { - "log": { - "properties": { - "geo": { - "properties": { - "coordinates": { - "type": "geo_point" - } + "properties": { + "geo": { + "properties": { + "coordinates": { + "type": "geo_point" } } } @@ -165,13 +161,13 @@ API to load the data sets: [source,shell] curl -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json -curl -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/shakespeare/doc/_bulk?pretty' --data-binary @shakespeare_6.0.json +curl -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/shakespeare/_bulk?pretty' --data-binary @shakespeare.json curl -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/_bulk?pretty' --data-binary @logs.jsonl Or for Windows users, in Powershell: [source,shell] Invoke-RestMethod "http://localhost:9200/bank/account/_bulk?pretty" -Method Post -ContentType 'application/x-ndjson' -InFile "accounts.json" -Invoke-RestMethod "http://localhost:9200/shakespeare/doc/_bulk?pretty" -Method Post -ContentType 'application/x-ndjson' -InFile "shakespeare_6.0.json" +Invoke-RestMethod "http://localhost:9200/shakespeare/_bulk?pretty" -Method Post -ContentType 'application/x-ndjson' -InFile "shakespeare.json" Invoke-RestMethod "http://localhost:9200/_bulk?pretty" -Method Post -ContentType 'application/x-ndjson' -InFile "logs.jsonl" These commands might take some time to execute, depending on the available computing resources. @@ -187,8 +183,8 @@ Your output should look similar to this: [source,shell] health status index pri rep docs.count docs.deleted store.size pri.store.size -yellow open bank 5 1 1000 0 418.2kb 418.2kb -yellow open shakespeare 5 1 111396 0 17.6mb 17.6mb -yellow open logstash-2015.05.18 5 1 4631 0 15.6mb 15.6mb -yellow open logstash-2015.05.19 5 1 4624 0 15.7mb 15.7mb -yellow open logstash-2015.05.20 5 1 4750 0 16.4mb 16.4mb +yellow open bank 1 1 1000 0 418.2kb 418.2kb +yellow open shakespeare 1 1 111396 0 17.6mb 17.6mb +yellow open logstash-2015.05.18 1 1 4631 0 15.6mb 15.6mb +yellow open logstash-2015.05.19 1 1 4624 0 15.7mb 15.7mb +yellow open logstash-2015.05.20 1 1 4750 0 16.4mb 16.4mb From 4a1e7a86fb6b2be4a7ec28fc4ac7d58283f87697 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 26 Mar 2019 16:17:02 -0400 Subject: [PATCH 39/96] [ML] Anomaly explorer add/remove filter via Top influencers list (#33626) * Add filter icons in Top influencers list * move entity component to own dir * upadte function name to applyFilter * add fix for IE overflow in anomalies table * update path to entityCell in test * Remove IE11 specific style * Update entityCell design for table+InfluencerList * Add entityCell component tests * remove injectI18n dep --- .../anomalies_table/_anomalies_table.scss | 19 --- .../anomalies_table/anomalies_table.test.js | 2 +- .../anomalies_table_columns.js | 3 +- .../anomalies_table/anomaly_details.js | 2 +- .../components/anomalies_table/entity_cell.js | 73 ---------- .../public/components/entity_cell/_index.scss | 1 + .../components/entity_cell/entity_cell.js | 129 ++++++++++++++++++ .../components/entity_cell/entity_cell.scss | 26 ++++ .../entity_cell/entity_cell.test.js | 36 +++++ .../ml/public/components/entity_cell/index.js | 7 + .../influencers_list/_influencers_list.scss | 8 +- .../influencers_list/influencers_list.js | 20 ++- x-pack/plugins/ml/public/explorer/explorer.js | 9 +- x-pack/plugins/ml/public/index.scss | 1 + 14 files changed, 229 insertions(+), 107 deletions(-) delete mode 100644 x-pack/plugins/ml/public/components/anomalies_table/entity_cell.js create mode 100644 x-pack/plugins/ml/public/components/entity_cell/_index.scss create mode 100644 x-pack/plugins/ml/public/components/entity_cell/entity_cell.js create mode 100644 x-pack/plugins/ml/public/components/entity_cell/entity_cell.scss create mode 100644 x-pack/plugins/ml/public/components/entity_cell/entity_cell.test.js create mode 100644 x-pack/plugins/ml/public/components/entity_cell/index.js diff --git a/x-pack/plugins/ml/public/components/anomalies_table/_anomalies_table.scss b/x-pack/plugins/ml/public/components/anomalies_table/_anomalies_table.scss index 24aac271706c4..e95eabdf510ad 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/_anomalies_table.scss +++ b/x-pack/plugins/ml/public/components/anomalies_table/_anomalies_table.scss @@ -51,20 +51,6 @@ font-size: inherit; } - .filter-button { - opacity: 0.3; - min-width: 14px; - - .euiIcon { - width: 14px; - height: 14px; - } - } - - .filter-button:hover { - opacity: 1; - } - .detector-rules-icon { margin-left: $euiSizeXS; opacity: 0.5; @@ -126,11 +112,6 @@ line-height: 1.5rem; } - .filter-button { - -webkit-transform: translateY(-1px); - transform: translateY(-1px); - } - } } diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.test.js b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.test.js index 2c4ba5f954ac4..75e9eb0c70555 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.test.js +++ b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.test.js @@ -24,7 +24,7 @@ jest.mock('../../services/field_format_service', () => ({ jest.mock('./links_menu', () => () =>
    mocked link component
    ); jest.mock('./description_cell', () => () =>
    mocked description component
    ); jest.mock('./detector_cell', () => () =>
    mocked detector component
    ); -jest.mock('./entity_cell', () => () =>
    mocked entity component
    ); +jest.mock('../entity_cell', () => () =>
    mocked entity component
    ); jest.mock('./influencers_cell', () => () =>
    mocked influencer component
    ); const columnData = { diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_columns.js b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_columns.js index ce2f7cbf49f5d..fcd6a7c5828d6 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_columns.js +++ b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_columns.js @@ -26,7 +26,7 @@ import { import { DescriptionCell } from './description_cell'; import { DetectorCell } from './detector_cell'; -import { EntityCell } from './entity_cell'; +import { EntityCell } from '../entity_cell'; import { InfluencersCell } from './influencers_cell'; import { LinksMenu } from './links_menu'; import { checkPermission } from '../../privilege/check_privilege'; @@ -137,6 +137,7 @@ export function getColumns( entityName={item.entityName} entityValue={entityValue} filter={filter} + wrapText={true} /> ), textOnly: true, diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.js b/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.js index bff8ba485bb8f..b1eada31fbf5b 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.js +++ b/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.js @@ -29,7 +29,7 @@ import { } from '@elastic/eui'; import { formatHumanReadableDateTimeSeconds } from '../../util/date_utils'; -import { EntityCell } from './entity_cell'; +import { EntityCell } from '../entity_cell'; import { getMultiBucketImpactLabel, getSeverity, diff --git a/x-pack/plugins/ml/public/components/anomalies_table/entity_cell.js b/x-pack/plugins/ml/public/components/anomalies_table/entity_cell.js deleted file mode 100644 index e35d83cae40c3..0000000000000 --- a/x-pack/plugins/ml/public/components/anomalies_table/entity_cell.js +++ /dev/null @@ -1,73 +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 PropTypes from 'prop-types'; -import React from 'react'; - -import { - EuiButtonIcon, - EuiToolTip -} from '@elastic/eui'; -import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; - -/* - * Component for rendering an entity in the anomalies table, displaying the value - * of the entity, such as a partitioning or influencer field value, and optionally links for - * adding or removing a filter on this entity. - */ -export const EntityCell = injectI18n(function EntityCell({ entityName, entityValue, filter, intl }) { - const valueText = (entityName !== 'mlcategory') ? entityValue : `mlcategory ${entityValue}`; - return ( - - {valueText} - {filter !== undefined && entityName !== undefined && entityValue !== undefined && - - } - > - filter(entityName, entityValue, '+')} - iconType="plusInCircle" - aria-label={intl.formatMessage({ - id: 'xpack.ml.anomaliesTable.entityCell.addFilterAriaLabel', - defaultMessage: 'Add filter' - })} - /> - - } - > - filter(entityName, entityValue, '-')} - iconType="minusInCircle" - aria-label={intl.formatMessage({ - id: 'xpack.ml.anomaliesTable.entityCell.removeFilterAriaLabel', - defaultMessage: 'Remove filter' - })} - /> - - - } - - ); -}); - -EntityCell.WrappedComponent.propTypes = { - entityName: PropTypes.string, - entityValue: PropTypes.any, - filter: PropTypes.func -}; diff --git a/x-pack/plugins/ml/public/components/entity_cell/_index.scss b/x-pack/plugins/ml/public/components/entity_cell/_index.scss new file mode 100644 index 0000000000000..04497c63a4642 --- /dev/null +++ b/x-pack/plugins/ml/public/components/entity_cell/_index.scss @@ -0,0 +1 @@ +@import 'entity_cell'; diff --git a/x-pack/plugins/ml/public/components/entity_cell/entity_cell.js b/x-pack/plugins/ml/public/components/entity_cell/entity_cell.js new file mode 100644 index 0000000000000..779af52198411 --- /dev/null +++ b/x-pack/plugins/ml/public/components/entity_cell/entity_cell.js @@ -0,0 +1,129 @@ +/* + * 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 PropTypes from 'prop-types'; +import React from 'react'; + +import { + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiToolTip +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; + + +function getAddFilter({ entityName, entityValue, filter }) { + return ( + } + > + filter(entityName, entityValue, '+')} + iconType="plusInCircle" + aria-label={i18n.translate('xpack.ml.anomaliesTable.entityCell.addFilterAriaLabel', { + defaultMessage: 'Add filter' + })} + /> + + ); +} + +function getRemoveFilter({ entityName, entityValue, filter }) { + return ( + } + > + filter(entityName, entityValue, '-')} + iconType="minusInCircle" + aria-label={i18n.translate('xpack.ml.anomaliesTable.entityCell.removeFilterAriaLabel', { + defaultMessage: 'Remove filter' + })} + /> + + ); +} + +/* + * Component for rendering an entity in the anomalies table, displaying the value + * of the entity, such as a partitioning or influencer field value, and optionally links for + * adding or removing a filter on this entity. + */ +export const EntityCell = function EntityCell({ + entityName, + entityValue, + filter, + wrapText = false +}) { + const valueText = (entityName !== 'mlcategory') ? entityValue : `mlcategory ${entityValue}`; + const textStyle = { maxWidth: '100%' }; + const textWrapperClass = (wrapText ? 'field-value-long' : 'field-value-short'); + const shouldDisplayIcons = (filter !== undefined && entityName !== undefined && entityValue !== undefined); + + if (wrapText === true) { + return ( +
    + {valueText} + {shouldDisplayIcons && + + {getAddFilter({ entityName, entityValue, filter })} + {getRemoveFilter({ entityName, entityValue, filter })} + + } +
    + ); + } else { + return ( + + + + {valueText} + + + {shouldDisplayIcons && + + + + {getAddFilter({ entityName, entityValue, filter })} + + + {getRemoveFilter({ entityName, entityValue, filter })} + + + + } + + ); + } +}; + +EntityCell.propTypes = { + entityName: PropTypes.string, + entityValue: PropTypes.any, + filter: PropTypes.func, + wrapText: PropTypes.bool +}; diff --git a/x-pack/plugins/ml/public/components/entity_cell/entity_cell.scss b/x-pack/plugins/ml/public/components/entity_cell/entity_cell.scss new file mode 100644 index 0000000000000..94446ae9816a5 --- /dev/null +++ b/x-pack/plugins/ml/public/components/entity_cell/entity_cell.scss @@ -0,0 +1,26 @@ +.field-value-short { + @include euiTextTruncate; + display: inline-block; + vertical-align: bottom; +} + +.field-value-long { + overflow-wrap: break-word; + // Known issue: IE11 text overflow within a flex container +} + +.filter-button { + opacity: 0.3; + min-width: 14px; + -webkit-transform: translateY(-1px); + transform: translateY(-1px); + + .euiIcon { + width: $euiFontSizeXS; + height: $euiFontSizeXS; + } +} + +.filter-button:hover { + opacity: 1; +} diff --git a/x-pack/plugins/ml/public/components/entity_cell/entity_cell.test.js b/x-pack/plugins/ml/public/components/entity_cell/entity_cell.test.js new file mode 100644 index 0000000000000..fd5c3dc6fa421 --- /dev/null +++ b/x-pack/plugins/ml/public/components/entity_cell/entity_cell.test.js @@ -0,0 +1,36 @@ +/* + * 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 { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { EntityCell } from './entity_cell'; + + +const defaultProps = { + entityName: 'Test Name', + entityValue: 'Test Value', + filter: () => {}, + wrapText: false +}; + +describe('EntityCell', () => { + + test('Icons are displayed when filter, entityName, and entityValue are defined', () => { + const wrapper = mountWithIntl(); + const icons = wrapper.find('EuiButtonIcon'); + + expect(icons.length).toBe(2); + }); + + test('Icons are not displayed when filter, entityName, or entityValue are undefined', () => { + const propsUndefinedFilter = { ...defaultProps, filter: undefined }; + const wrapper = mountWithIntl(); + const icons = wrapper.find('EuiButtonIcon'); + + expect(icons.length).toBe(0); + }); + +}); diff --git a/x-pack/plugins/ml/public/components/entity_cell/index.js b/x-pack/plugins/ml/public/components/entity_cell/index.js new file mode 100644 index 0000000000000..f66a9f7025d62 --- /dev/null +++ b/x-pack/plugins/ml/public/components/entity_cell/index.js @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { EntityCell } from './entity_cell'; diff --git a/x-pack/plugins/ml/public/components/influencers_list/_influencers_list.scss b/x-pack/plugins/ml/public/components/influencers_list/_influencers_list.scss index b632b98b75b7c..efaff421cdf6a 100644 --- a/x-pack/plugins/ml/public/components/influencers_list/_influencers_list.scss +++ b/x-pack/plugins/ml/public/components/influencers_list/_influencers_list.scss @@ -4,11 +4,11 @@ .field-label { font-size: $euiFontSizeXS; text-align: left; + max-height: $euiFontSizeS; + max-width: calc(100% - 102px); // SASSTODO: Calc proper value .field-value { @include euiTextTruncate; - - max-width: calc(100% - 34px); // SASSTODO: Calc proper value display: inline-block; vertical-align: bottom; } @@ -29,7 +29,7 @@ .progress-bar { height: $euiSizeXS / 2; - margin-top: $euiSizeS; + margin-top: $euiSizeM; text-align: right; line-height: 18px; // SASSTODO: Calc porper value display: inline-block; @@ -93,7 +93,7 @@ line-height: 14px; border-radius: $euiBorderRadius; padding: $euiSizeXS / 2; - margin-top: 1px; + margin-top: 3px; display: inline-block; border: $euiBorderThin; } diff --git a/x-pack/plugins/ml/public/components/influencers_list/influencers_list.js b/x-pack/plugins/ml/public/components/influencers_list/influencers_list.js index b7c1ae85e54e0..7794d3fd23497 100644 --- a/x-pack/plugins/ml/public/components/influencers_list/influencers_list.js +++ b/x-pack/plugins/ml/public/components/influencers_list/influencers_list.js @@ -24,6 +24,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { abbreviateWholeNumber } from 'plugins/ml/formatters/abbreviate_whole_number'; import { getSeverity } from 'plugins/ml/../common/util/anomaly_utils'; +import { EntityCell } from '../entity_cell'; function getTooltipContent(maxScoreLabel, totalScoreLabel) { @@ -47,7 +48,7 @@ function getTooltipContent(maxScoreLabel, totalScoreLabel) { ); } -function Influencer({ influencerFieldName, valueData }) { +function Influencer({ influencerFieldName, influencerFilter, valueData }) { const maxScorePrecise = valueData.maxAnomalyScore; const maxScore = parseInt(maxScorePrecise); const maxScoreLabel = (maxScore !== 0) ? maxScore : '< 1'; @@ -67,7 +68,11 @@ function Influencer({ influencerFieldName, valueData }) {
    {(influencerFieldName !== 'mlcategory') ? ( -
    {valueData.influencerFieldValue}
    + ) : (
    mlcategory {valueData.influencerFieldValue}
    )} @@ -102,14 +107,16 @@ function Influencer({ influencerFieldName, valueData }) { } Influencer.propTypes = { influencerFieldName: PropTypes.string.isRequired, + influencerFilter: PropTypes.func, valueData: PropTypes.object.isRequired }; -function InfluencersByName({ influencerFieldName, fieldValues }) { +function InfluencersByName({ influencerFieldName, influencerFilter, fieldValues }) { const influencerValues = fieldValues.map(valueData => ( )); @@ -126,10 +133,11 @@ function InfluencersByName({ influencerFieldName, fieldValues }) { } InfluencersByName.propTypes = { influencerFieldName: PropTypes.string.isRequired, + influencerFilter: PropTypes.func, fieldValues: PropTypes.array.isRequired }; -export function InfluencersList({ influencers }) { +export function InfluencersList({ influencers, influencerFilter }) { if (influencers === undefined || Object.keys(influencers).length === 0) { return ( @@ -153,6 +161,7 @@ export function InfluencersList({ influencers }) { )); @@ -164,5 +173,6 @@ export function InfluencersList({ influencers }) { ); } InfluencersList.propTypes = { - influencers: PropTypes.object + influencers: PropTypes.object, + influencerFilter: PropTypes.func, }; diff --git a/x-pack/plugins/ml/public/explorer/explorer.js b/x-pack/plugins/ml/public/explorer/explorer.js index d3a178709fb8e..444cdf5acc721 100644 --- a/x-pack/plugins/ml/public/explorer/explorer.js +++ b/x-pack/plugins/ml/public/explorer/explorer.js @@ -926,7 +926,7 @@ export const Explorer = injectI18n(injectObservablesAsProps( } } - applyFilterFromTable = (fieldName, fieldValue, action) => { + applyFilter = (fieldName, fieldValue, action) => { let newQueryString = ''; const { queryString } = this.state; const operator = 'and '; @@ -1107,7 +1107,10 @@ export const Explorer = injectI18n(injectObservablesAsProps( defaultMessage="Top Influencers" /> - +
    )} @@ -1292,7 +1295,7 @@ export const Explorer = injectI18n(injectObservablesAsProps(
    diff --git a/x-pack/plugins/ml/public/index.scss b/x-pack/plugins/ml/public/index.scss index c31c1c2804c96..5d2c4628b6357 100644 --- a/x-pack/plugins/ml/public/index.scss +++ b/x-pack/plugins/ml/public/index.scss @@ -31,6 +31,7 @@ @import 'components/controls/index'; @import 'components/data_recognizer/index'; @import 'components/documentation_help_link/index'; + @import 'components/entity_cell/index'; @import 'components/field_data_card/index'; // SASSTODO: This file needs to be rewritten @import 'components/field_title_bar/index'; @import 'components/field_type_icon/index'; From 20bdf7d4a9846f8be5f9e6426d97372e974651ac Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 26 Mar 2019 20:44:03 +0000 Subject: [PATCH 40/96] Migration to Babel7 and @babel/preset-typescript (#33093) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(NA): first changes on every package.json order to support new babel 7. chore(NA): build for kbn-pm with babel 7. * chore(NA): patch babel register to load typescrit * chore(NA): first working version with babel 7 replacing typescript compiler. * fix(NA): common preset declaration in order to make it work with babel-loader. * chore(na): organizing babel preset env package json. * chore(NA): mocha tests enabled. * fix(NA): typo on importing * test(NA): majority of x-pack tests ported to use babel-jest * fix(NA): report info button test with babel-jest. * fix(NA): polling service tests. * test(na): fix server plugins plugin tests. * test(NA): batch of test fixs for jest tests under babel-jest hoisting. * chore(NA): add babel plugin to hoist mock prefixed vars on jest tests. * chore(NA): update yarn.lock file. * chore(NA): tests passing. * chore(NA): remove wrong dep * chore(NA): fix tsconfig * chore(NA): skip babel for ts-jest. * chore(NA): selectively apply the plugin to strip off namespace from ts files. * chore(NA): remove not needed changes from ts tests * chore(NA): removed ts-jest dependency. chore(NA): migrate ts tests on x-pack to use babel-jest with the new pattern. * chore(NA): migrate kibana default distribution typescript tests to run with babel-jest and the new test mock pattern. * chore(NA): merge and solve conflicts with master. * chore(NA): fix problems reported by eslint * chore(NA): fix license ovveride for babel-plugin-mock-imports * chore(NA): update jest integration tests for kbn pm * chore(NA): update babel jest integration tests for kbn pm. * test(NA): update jest integration snapshot for kbn pm. * chore(NA): apply changes according to the pull request reviews. * chore(NA): apply changes according to the pull request reviews. * refact(NA): migrate jest tests to the new pattern. * fix(NA): babel 7 polyfill in the tests bundle. * chore(NA): restore needed step in order to compile x-pack with typescript. * chore(NA): change build to compile typescript with babel for the oss code. chore(NA): change transpile typescript task to only transpile types for x-pack. refact(NA): common preset for babel 7 * Revert "chore(NA): change build to compile typescript with babel for the oss code. chore(NA): change transpile typescript task to only transpile types for x-pack. refact(NA): common preset for babel 7" This reverts commit 2707d538f5126c582a00580a8489361592c80d70. * fix(NA): import paths for tabConfigConst * chore(NA): fix transpiling error on browser tests * chore(NA): simplify kbn babel preset package. * chore(NA): migrate build to use babel transpiler for typescript excluding xpack. * fix(NA): introduced error on test quick task. * fix(NA): fix preset for client side code on build. * fix(NA): build with babel * fix(NA): negated patterns in the end. * fix(NA): kbn_tp_sample_panel_action creation. * fix(NA): babel typescript transform plugin workaround when exporting interface name. * refact(NA): remove not needed type cast to any on jest test. * docs(NA): add developement documentation about jest mocks test pattern. * chore(NA): missing unmerged path. * chore(NA): fix jest tests for template. * [CCR] Client integration tests (table lists) (#33525) * Force user to re-authenticate if token refresh fails with `400` status code. (#33774) * Improve performance of the Logstash Pipeline Viewer (#33793) Resolves #27513. _This PR is a combination of #31293 (the code changes) + #33570 (test updates). These two PRs were individually reviewed and merged into a feature branch. This combo PR here simply sets up the merge from the feature branch to `master`._ Summary of changes, taken from #31293: ## Before this PR The Logstash Pipeline Viewer UI would make a single Kibana API call to fetch all the information necessary to render the Logstash pipeline. This included information necessary to render the detail drawer that opens up when a user clicks on an individual vertex in the pipeline. Naturally, this single API call fetched _a lot_ of data, not just from the Kibana server but also, in turn, from Elasticsearch as well. The "pro" of this approach was that the user would see instantaneous results if they clicked on a vertex in a pipeline and opened the detail drawer for that vertex. The "cons" were the amount of computation Elasticsearch had to perform and the amount of data being transferred over the wire between Elasticsearch and the Kibana server as well as between the Kibana server and the browser. ## With this PR This PR makes the Kibana API call to fetch data necessary for **initially** rendering the pipeline — that is, with the detail drawer closed — much lighter. When the user clicks on a vertex in a pipeline, a second API call is then made to fetch data necessary for the detail drawer. ## Gains, by the numbers Based on a simple, 1-input, 1-filter, and 1-output pipeline. * Before this PR, the Elasticsearch `logstash_stats` API responses (multiple calls were made using the `composite` aggregation over the `date_histogram` aggregation) generated a total of 1228 aggregation buckets (before any `filter_path`s were applied but across all `composite` "pages"). With this PR, the single `logstash_stats` API response (note that this is just for the initial rendering of the pipeline, with the detail drawer closed) generated 12 buckets (also before any `filter_path`s were applied). That's a **99.02% reduction** in number of buckets. * Before this PR, the Elasticsearch `logstash_stats` API responses added up to 70319 bytes. With this PR, the single `logstash_stats` API response for the same pipeline is 746 bytes. That's a **98.93% reduction** in size. * Before this PR, the Elasticsearch `logstash_state` API response was 7718 bytes. With this PR, the API response for the same pipeline is 2328 bytes. That's a **69.83% reduction** in size. * Before this PR the Kibana API response was 51777 bytes. With this PR, the API response for the same pipeline is 2567 bytes (again, note that this is just for the initial rendering of the pipeline, with the detail drawer closed). That's a **95.04% reduction** in size. * [Maps] split settings into layer and source panels (#33788) * [Maps] split settings into layer and source panels * fix SCSS import * [env] exit if starting as root (#21563) * [env] exit if starting as root * fix windows * s/--allow-root * Typescript sample panel action (#33602) * Typescript sample panel action * Update EUI version to match main cabana version * update yarn.lock * add back typings include * use correct relative path * Home page "recent links" should communicate saved object type #21896 (#33694) * adds object type for screen order * adds object type for pointer hovering * Update src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx Co-Authored-By: rockfield --- docs/development/core-development.asciidoc | 2 + .../core/development-unit-tests.asciidoc | 80 + package.json | 39 +- packages/elastic-datemath/.babelrc | 23 +- packages/elastic-datemath/package.json | 6 +- packages/eslint-config-kibana/package.json | 16 +- packages/kbn-babel-code-parser/package.json | 2 +- packages/kbn-babel-preset/common_preset.js | 25 +- packages/kbn-babel-preset/common_preset_7.js | 39 - packages/kbn-babel-preset/node_preset.js | 57 +- packages/kbn-babel-preset/node_preset_7.js | 50 - packages/kbn-babel-preset/package.json | 14 +- packages/kbn-babel-preset/webpack_preset.js | 35 +- packages/kbn-dev-utils/package.json | 2 +- .../kbn-eslint-plugin-eslint/package.json | 4 +- packages/kbn-i18n/tsconfig.json | 40 +- packages/kbn-interpreter/.babelrc | 3 +- packages/kbn-interpreter/package.json | 11 +- .../tasks/build/server_code_transformer.js | 2 +- .../build/server_code_transformer.test.js | 9 +- .../template/package_template.json | 16 +- packages/kbn-plugin-helpers/lib/utils.js | 2 +- packages/kbn-pm/.babelrc | 10 +- packages/kbn-pm/dist/index.js | 3312 ++++++++--------- packages/kbn-pm/package.json | 11 +- .../__fixtures__/packages/bar/package.json | 7 +- .../__fixtures__/packages/foo/package.json | 7 +- .../build_production_projects.test.ts.snap | 14 +- packages/kbn-pm/tsconfig.json | 2 +- packages/kbn-pm/webpack.config.js | 9 - packages/kbn-test/babel.config.js | 2 +- packages/kbn-test/package.json | 4 +- .../kbn-ui-framework/doc_site/src/index.js | 2 +- packages/kbn-ui-framework/package.json | 12 +- src/core/public/core_system.test.mocks.ts | 92 + src/core/public/core_system.test.ts | 87 +- .../fatal_errors_screen.test.tsx.snap | 3 +- .../fatal_errors_service.test.mocks.ts | 25 + .../fatal_errors/fatal_errors_service.test.ts | 7 +- .../toasts/toasts_service.test.mocks.ts | 25 + .../toasts/toasts_service.test.tsx | 7 +- .../ui_settings_service.test.mocks.ts | 57 + .../ui_settings/ui_settings_service.test.ts | 39 +- src/core/server/config/config_service.mock.ts | 1 + .../config/config_service.test.mocks.ts | 21 + src/core/server/config/config_service.test.ts | 3 +- src/core/server/config/env.test.mocks.ts | 33 + src/core/server/config/env.test.ts | 15 +- .../config/raw_config_service.test.mocks.ts | 24 + .../server/config/raw_config_service.test.ts | 6 +- .../cluster_client.test.mocks.ts | 35 + .../elasticsearch/cluster_client.test.ts | 21 +- ...elasticsearch_client_config.test.mocks.ts} | 4 +- .../elasticsearch_client_config.test.ts | 7 +- .../elasticsearch_service.mock.ts | 1 + .../elasticsearch_service.test.mocks.ts | 21 + .../elasticsearch_service.test.ts | 3 +- src/core/server/http/http_service.mock.ts | 1 + .../server/http/http_service.test.mocks.ts | 24 + src/core/server/http/http_service.test.ts | 6 +- src/core/server/index.test.mocks.ts | 40 + .../__snapshots__/legacy_service.test.ts.snap | 2 + .../logging/appenders/appenders.test.mocks.ts | 29 + .../logging/appenders/appenders.test.ts | 11 +- .../file/file_appender.test.mocks.ts | 32 + .../appenders/file/file_appender.test.ts | 14 +- .../discovery/plugin_discovery.test.mocks.ts | 30 + .../discovery/plugin_discovery.test.ts | 12 +- .../plugin_manifest_parser.test.mocks.ts | 22 + .../discovery/plugin_manifest_parser.test.ts | 4 +- src/core/server/plugins/plugin.test.ts | 6 +- .../plugins/plugins_service.test.mocks.ts | 26 + .../server/plugins/plugins_service.test.ts | 8 +- .../plugins/plugins_system.test.mocks.ts | 23 + .../server/plugins/plugins_system.test.ts | 8 +- src/core/server/root/index.test.mocks.ts | 33 + src/core/server/root/index.test.ts | 15 +- src/core/server/server.test.ts | 28 +- src/dev/build/build_distributables.js | 6 +- src/dev/build/tasks/copy_source_task.js | 3 +- src/dev/build/tasks/index.js | 2 +- src/dev/build/tasks/transpile_babel_task.js | 72 +- ...t_task.js => typecheck_typescript_task.js} | 30 +- .../i18n/integrate_locale_files.test.mocks.ts | 27 + src/dev/i18n/integrate_locale_files.test.ts | 9 +- src/dev/jest/babel_transform.js | 2 +- src/dev/jest/config.js | 8 +- src/dev/jest/setup/babel_polyfill.js | 2 +- src/dev/jest/ts_transform.ts | 74 - src/dev/license_checker/config.js | 2 +- src/dev/mocha/run_mocha_cli.js | 2 +- .../data/__snapshots__/data_view.test.js.snap | 2 + .../interpreter/common/types/register.js | 2 +- .../__snapshots__/new_vis_modal.test.tsx.snap | 29 +- .../wizard/new_vis_modal.test.mocks.ts | 26 + .../visualize/wizard/new_vis_modal.test.tsx | 8 +- .../tests_bundle/tests_entry_template.js | 2 +- .../__snapshots__/help_flyout.test.js.snap | 4 +- .../language_switcher.test.tsx.snap | 8 +- .../components/query_bar.test.mocks.ts | 70 + .../query_bar/components/query_bar.test.tsx | 57 +- .../suggestions_component.test.tsx.snap | 8 +- .../url_panel_content.test.js.snap | 16 +- .../utils/subscribe_with_scope.test.mocks.ts | 23 + .../public/utils/subscribe_with_scope.test.ts | 6 +- .../editors/default/agg_param_editor_props.ts | 8 +- .../embedded_visualize_handler.test.mocks.ts | 67 + .../loader/embedded_visualize_handler.test.ts | 50 +- .../loader/pipeline_helpers/utilities.ts | 2 +- .../ui/ui_bundles/app_entry_template.js | 2 +- src/optimize/base_optimizer.js | 52 +- src/optimize/watch/watch_cache.ts | 11 +- src/setup_node_env/babel_register/index.js | 10 - src/setup_node_env/babel_register/polyfill.js | 8 +- src/setup_node_env/babel_register/register.js | 11 +- x-pack/dev-tools/jest/create_jest_config.js | 3 +- x-pack/package.json | 20 +- .../DiscoverLinks.integration.test.tsx | 2 - .../__test__/tabConfig.test.tsx | 59 +- .../shared/PropertiesTable/tabConfig.ts | 117 +- .../shared/PropertiesTable/tabConfigConst.ts | 119 + .../canvas/.storybook/webpack.config.js | 2 +- .../public/components/workpad_page/index.js | 1 + .../lib/aeroelastic/layout_functions.js | 1 + .../plugins/canvas/tasks/helpers/babelhook.js | 2 +- .../scripts/generate_types_from_graphql.js | 1 - .../__snapshots__/form_label.test.js.snap | 4 +- .../__snapshots__/suggestions.test.js.snap | 4 +- x-pack/plugins/monitoring/README.md | 2 +- .../collection_enabled.test.js.snap | 4 +- .../collection_interval.test.js.snap | 8 +- .../report_info_button.test.mocks.ts | 8 + .../components/report_info_button.test.tsx | 3 +- .../public/components/report_listing.tsx | 4 +- .../components/reporting_panel_content.tsx | 13 +- x-pack/plugins/searchprofiler/README.md | 2 +- .../privilege_callout_warning.test.tsx.snap | 8 +- .../space_aware_privilege_form.test.tsx.snap | 7 +- .../lib/authorization/privileges.test.js | 2 +- .../__snapshots__/space_avatar.test.tsx.snap | 4 +- .../advanced_settings_title.test.tsx.snap | 2 +- .../space_identifier.test.tsx.snap | 3 +- .../spaces_grid_pages.test.tsx.snap | 14 +- .../nav_control_popover.test.tsx.snap | 4 +- .../__snapshots__/checkup_tab.test.tsx.snap | 4 +- .../checklist_step.test.tsx.snap | 8 +- .../__snapshots__/warning_step.test.tsx.snap | 8 +- .../reindex/flyout/progress.test.tsx | 4 +- .../reindex/polling_service.test.mocks.ts | 24 + .../reindex/polling_service.test.ts | 20 +- .../server/lib/reindexing/worker.ts | 2 +- .../__snapshots__/snapshot.test.tsx.snap | 2 +- .../__snapshots__/empty_state.test.tsx.snap | 32 +- .../uptime/scripts/infer_graphql_types.js | 1 - .../server/lib/file_integrity.test.mocks.ts | 28 + .../server/lib/file_integrity.test.ts | 23 +- x-pack/tasks/build.js | 2 +- .../plugins/task_manager/package.json | 10 +- .../common/services/es.js | 3 +- x-pack/test_utils/jest/config.js | 8 +- yarn.lock | 1513 ++------ 161 files changed, 3586 insertions(+), 4030 deletions(-) create mode 100644 docs/development/core/development-unit-tests.asciidoc delete mode 100644 packages/kbn-babel-preset/common_preset_7.js delete mode 100644 packages/kbn-babel-preset/node_preset_7.js create mode 100644 src/core/public/core_system.test.mocks.ts create mode 100644 src/core/public/fatal_errors/fatal_errors_service.test.mocks.ts create mode 100644 src/core/public/notifications/toasts/toasts_service.test.mocks.ts create mode 100644 src/core/public/ui_settings/ui_settings_service.test.mocks.ts create mode 100644 src/core/server/config/config_service.test.mocks.ts create mode 100644 src/core/server/config/env.test.mocks.ts create mode 100644 src/core/server/config/raw_config_service.test.mocks.ts create mode 100644 src/core/server/elasticsearch/cluster_client.test.mocks.ts rename src/{dev/jest/ts_transform.js => core/server/elasticsearch/elasticsearch_client_config.test.mocks.ts} (88%) create mode 100644 src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts create mode 100644 src/core/server/http/http_service.test.mocks.ts create mode 100644 src/core/server/index.test.mocks.ts create mode 100644 src/core/server/logging/appenders/appenders.test.mocks.ts create mode 100644 src/core/server/logging/appenders/file/file_appender.test.mocks.ts create mode 100644 src/core/server/plugins/discovery/plugin_discovery.test.mocks.ts create mode 100644 src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts create mode 100644 src/core/server/plugins/plugins_service.test.mocks.ts create mode 100644 src/core/server/plugins/plugins_system.test.mocks.ts create mode 100644 src/core/server/root/index.test.mocks.ts rename src/dev/build/tasks/{transpile_typescript_task.js => typecheck_typescript_task.js} (85%) create mode 100644 src/dev/i18n/integrate_locale_files.test.mocks.ts delete mode 100644 src/dev/jest/ts_transform.ts create mode 100644 src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts create mode 100644 src/legacy/ui/public/query_bar/components/query_bar.test.mocks.ts create mode 100644 src/legacy/ui/public/utils/subscribe_with_scope.test.mocks.ts create mode 100644 src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts create mode 100644 x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts create mode 100644 x-pack/plugins/reporting/public/components/report_info_button.test.mocks.ts create mode 100644 x-pack/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts create mode 100644 x-pack/plugins/xpack_main/server/lib/file_integrity.test.mocks.ts diff --git a/docs/development/core-development.asciidoc b/docs/development/core-development.asciidoc index 45f52c16ee332..ed04a6f12eae9 100644 --- a/docs/development/core-development.asciidoc +++ b/docs/development/core-development.asciidoc @@ -15,4 +15,6 @@ include::core/development-modules.asciidoc[] include::core/development-elasticsearch.asciidoc[] +include::core/development-unit-tests.asciidoc[] + include::core/development-functional-tests.asciidoc[] diff --git a/docs/development/core/development-unit-tests.asciidoc b/docs/development/core/development-unit-tests.asciidoc new file mode 100644 index 0000000000000..852d1fef6b32a --- /dev/null +++ b/docs/development/core/development-unit-tests.asciidoc @@ -0,0 +1,80 @@ +[[development-unit-tests]] +=== Unit Testing + +We use unit tests to make sure that individual software units of Kibana perform as they were designed to. + +[float] +==== Current Frameworks + +Kibana is migrating unit testing from `Mocha` to `Jest`. Legacy unit tests still exist in `Mocha` but all new unit tests should be written in `Jest`. + +[float] +==== Mocha (legacy) + +Mocha tests are contained in `__tests__` directories. + +===== Running Mocha Unit Tests + +["source","shell"] +----------- +yarn test:mocha +----------- + +==== Jest +Jest tests are stored in the same directory as source code files with the `.test.{js,ts,tsx}` suffix. + +===== Running Jest Unit Tests + +["source","shell"] +----------- +yarn test:jest +----------- + +===== Writing Jest Unit Tests + +In order to write those tests there are two main things you need to be aware of. +The first one is the different between `jest.mock` and `jest.doMock` +and the second one our `jest mocks file pattern`. As we are running `js` and `ts` +test files with `babel-jest` both techniques are needed +specially for the tests implemented on Typescript in order to benefit from the +auto-inference types feature. + + +====== Jest.mock vs Jest.doMock + +Both methods are essentially the same on their roots however the `jest.mock` +calls will get hoisted to the top of the file and can only reference variables +prefixed with `mock`. On the other hand, `jest.doMock` won't be hoisted and can +reference pretty much any variable we want, however we have to assure those referenced +variables are instantiated at the time we need them which lead us to the next +section where we'll talk about our jest mock files pattern. + +====== Jest Mock Files Pattern + +Specially on typescript it is pretty common to have in unit tests +`jest.doMock` calls which reference for example imported types. Any error +will thrown from doing that however the test will fail. The reason behind that +is because despite the `jest.doMock` isn't being hoisted by `babel-jest` the +import with the types we are referencing will be hoisted to the top and at the +time we'll call the function that variable would not be defined. + +In order to prevent that we develop a protocol that should be followed: + +- Each module could provide a standard mock in `mymodule.mock.ts` in case +there are other tests that could benefit from using definitions here. +This file would not have any `jest.mock` calls, just dummy objects. + +- Each test defines its mocks in `mymodule.test.mocks.ts`. This file +could import relevant mocks from the generalised module's mocks +file `(*.mock.ts)` and call `jest.mock` for each of them. If there is +any relevant dummy mock objects to generalise (and to be used by +other tests), the dummy objects could be defined directly on this file. + +- Each test would import its mocks from the test mocks +file mymodule.test.mocks.ts. `mymodule.test.ts` has an import +like: `import * as Mocks from './mymodule.test.mocks'`, +`import { mockX } from './mymodule.test.mocks'` +or just `import './mymodule.test.mocks'` if there isn't anything +exported to be used. + + diff --git a/package.json b/package.json index 43f6c6704c600..3d3a64a56e671 100644 --- a/package.json +++ b/package.json @@ -94,6 +94,9 @@ ] }, "dependencies": { + "@babel/core": "^7.3.4", + "@babel/polyfill": "^7.2.5", + "@babel/register": "^7.0.0", "@elastic/datemath": "5.0.2", "@elastic/eui": "9.5.0", "@elastic/filesaver": "1.1.2", @@ -123,10 +126,7 @@ "angular-sanitize": "1.6.5", "angular-sortable-view": "0.0.15", "autoprefixer": "^9.1.0", - "babel-core": "6.26.3", - "babel-loader": "7.1.5", - "babel-polyfill": "6.26.0", - "babel-register": "6.26.0", + "babel-loader": "8.0.5", "bluebird": "3.5.3", "boom": "^7.2.0", "brace": "0.11.1", @@ -263,7 +263,7 @@ "@octokit/rest": "^15.10.0", "@types/angular": "1.6.50", "@types/angular-mocks": "^1.7.0", - "@types/babel-core": "^6.25.5", + "@types/babel__core": "^7.1.0", "@types/bluebird": "^3.1.1", "@types/boom": "^7.2.0", "@types/chance": "^1.0.0", @@ -275,7 +275,7 @@ "@types/delete-empty": "^2.0.0", "@types/elasticsearch": "^5.0.30", "@types/enzyme": "^3.1.12", - "@types/eslint": "^4.16.2", + "@types/eslint": "^4.16.6", "@types/execa": "^0.9.0", "@types/fetch-mock": "7.2.1", "@types/getopts": "^2.0.0", @@ -320,8 +320,8 @@ "@types/zen-observable": "^0.8.0", "angular-mocks": "1.4.7", "archiver": "^3.0.0", - "babel-eslint": "^9.0.0", - "babel-jest": "^23.6.0", + "babel-eslint": "^10.0.1", + "babel-jest": "^24.1.0", "backport": "4.4.1", "chai": "3.5.0", "chance": "1.0.10", @@ -335,17 +335,17 @@ "enzyme-adapter-react-16": "^1.9.0", "enzyme-adapter-utils": "^1.10.0", "enzyme-to-json": "^3.3.4", - "eslint": "^5.6.0", - "eslint-config-prettier": "^3.1.0", - "eslint-plugin-babel": "^5.2.0", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-jest": "^21.26.2", - "eslint-plugin-jsx-a11y": "^6.1.2", - "eslint-plugin-mocha": "^5.2.0", + "eslint": "^5.15.1", + "eslint-config-prettier": "^4.1.0", + "eslint-plugin-babel": "^5.3.0", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-jest": "^22.3.0", + "eslint-plugin-jsx-a11y": "^6.2.1", + "eslint-plugin-mocha": "^5.3.0", "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", - "eslint-plugin-prettier": "^2.6.2", - "eslint-plugin-react": "^7.11.1", + "eslint-plugin-prettier": "^3.0.1", + "eslint-plugin-react": "^7.12.4", "faker": "1.1.0", "fetch-mock": "7.3.0", "geckodriver": "1.12.2", @@ -356,7 +356,7 @@ "grunt-karma": "2.0.0", "grunt-peg": "^2.0.1", "grunt-run": "0.7.0", - "gulp-babel": "^7.0.1", + "gulp-babel": "^8.0.0", "gulp-sourcemaps": "2.6.4", "has-ansi": "^3.0.0", "image-diff": "1.6.0", @@ -402,9 +402,6 @@ "supertest": "^3.1.0", "supertest-as-promised": "^4.0.2", "tree-kill": "^1.1.0", - "ts-jest": "^23.1.4", - "ts-loader": "^5.2.2", - "ts-node": "^7.0.1", "tslint": "^5.11.0", "tslint-config-prettier": "^1.15.0", "tslint-microsoft-contrib": "^6.0.0", diff --git a/packages/elastic-datemath/.babelrc b/packages/elastic-datemath/.babelrc index e39c0afafdd9b..26138d48b71b7 100644 --- a/packages/elastic-datemath/.babelrc +++ b/packages/elastic-datemath/.babelrc @@ -1,13 +1,16 @@ { - "presets": [["env", { - "targets": { - "node": "current", - "browsers": [ - "last 2 versions", - "> 5%", - "Safari 7", - ] + "presets": [ + ["@babel/preset-env", { + "targets": { + "node": "current", + "browsers": [ + "last 2 versions", + "> 5%", + "Safari 7" + ] + } } - }]], + ] + ], "plugins": ["add-module-exports"] -} \ No newline at end of file +} diff --git a/packages/elastic-datemath/package.json b/packages/elastic-datemath/package.json index 3b626077f5eaf..77c545709a3cf 100644 --- a/packages/elastic-datemath/package.json +++ b/packages/elastic-datemath/package.json @@ -11,9 +11,9 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "babel-cli": "^6.26.0", - "babel-plugin-add-module-exports": "^0.2.1", - "babel-preset-env": "^1.7.0", + "@babel/cli": "^7.2.3", + "@babel/preset-env": "^7.3.4", + "babel-plugin-add-module-exports": "^1.0.0", "moment": "^2.13.0" }, "dependencies": { diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json index d2e639eebbbe3..c4a5a99e4c976 100644 --- a/packages/eslint-config-kibana/package.json +++ b/packages/eslint-config-kibana/package.json @@ -15,15 +15,15 @@ }, "homepage": "https://github.com/elastic/eslint-config-kibana#readme", "peerDependencies": { - "babel-eslint": "^9.0.0", - "eslint": "^5.6.0", - "eslint-plugin-babel": "^5.2.0", - "eslint-plugin-jsx-a11y": "^6.1.2", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-jest": "^21.22.1", - "eslint-plugin-mocha": "^5.2.0", + "babel-eslint": "^10.0.1", + "eslint": "^5.14.1", + "eslint-plugin-babel": "^5.3.0", + "eslint-plugin-jsx-a11y": "^6.2.1", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-jest": "^22.3.0", + "eslint-plugin-mocha": "^5.3.0", "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", - "eslint-plugin-react": "^7.11.1" + "eslint-plugin-react": "^7.12.4" } } diff --git a/packages/kbn-babel-code-parser/package.json b/packages/kbn-babel-code-parser/package.json index 23e7c29f22dfd..addc530285659 100755 --- a/packages/kbn-babel-code-parser/package.json +++ b/packages/kbn-babel-code-parser/package.json @@ -15,7 +15,7 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "babel-cli": "^6.26.0" + "@babel/cli": "^7.2.3" }, "dependencies": { "@kbn/babel-preset": "1.0.0", diff --git a/packages/kbn-babel-preset/common_preset.js b/packages/kbn-babel-preset/common_preset.js index a2d4495adc54b..e67a2db5a3800 100644 --- a/packages/kbn-babel-preset/common_preset.js +++ b/packages/kbn-babel-preset/common_preset.js @@ -19,20 +19,33 @@ module.exports = { presets: [ - require.resolve('babel-preset-react'), + require.resolve('@babel/preset-typescript'), + require.resolve('@babel/preset-react') ], plugins: [ require.resolve('babel-plugin-add-module-exports'), - // stage 3 - require.resolve('babel-plugin-transform-async-generator-functions'), - require.resolve('babel-plugin-transform-object-rest-spread'), - // the class properties proposal was merged with the private fields proposal + // The class properties proposal was merged with the private fields proposal // into the "class fields" proposal. Babel doesn't support this combined // proposal yet, which includes private field, so this transform is // TECHNICALLY stage 2, but for all intents and purposes it's stage 3 // // See https://github.com/babel/proposals/issues/12 for progress - require.resolve('babel-plugin-transform-class-properties'), + require.resolve('@babel/plugin-proposal-class-properties'), ], + overrides: [ + { + // Babel 7 don't support the namespace feature on typescript code. + // With namespaces only used for type declarations, we can securely + // strip them off for babel on x-pack infra plugin + // + // See https://github.com/babel/babel/issues/8244#issuecomment-466548733 + test: /x-pack[\/\\]plugins[\/\\]infra[\/\\].*[\/\\]graphql/, + plugins: [ + [ + require.resolve('babel-plugin-typescript-strip-namespaces'), + ], + ] + } + ] }; diff --git a/packages/kbn-babel-preset/common_preset_7.js b/packages/kbn-babel-preset/common_preset_7.js deleted file mode 100644 index df72f382e2b0a..0000000000000 --- a/packages/kbn-babel-preset/common_preset_7.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. - */ - -module.exports = { - presets: [ - require.resolve('@babel/preset-react'), - require.resolve('@babel/preset-typescript'), - ], - plugins: [ - require.resolve('babel7-plugin-add-module-exports'), - // stage 3 - require.resolve('@babel/plugin-proposal-async-generator-functions'), - require.resolve('@babel/plugin-proposal-object-rest-spread'), - - // the class properties proposal was merged with the private fields proposal - // into the "class fields" proposal. Babel doesn't support this combined - // proposal yet, which includes private field, so this transform is - // TECHNICALLY stage 2, but for all intents and purposes it's stage 3 - // - // See https://github.com/babel/proposals/issues/12 for progress - require.resolve('@babel/plugin-proposal-class-properties'), - ], -}; diff --git a/packages/kbn-babel-preset/node_preset.js b/packages/kbn-babel-preset/node_preset.js index 04d6dd3609e8a..ac4dc17e63803 100644 --- a/packages/kbn-babel-preset/node_preset.js +++ b/packages/kbn-babel-preset/node_preset.js @@ -17,34 +17,37 @@ * under the License. */ -module.exports = { - presets: [ - [ - require.resolve('babel-preset-env'), - { - targets: { - // only applies the necessary transformations based on the - // current node.js processes version. For example: running - // `nvm install 8 && node ./src/cli` will run kibana in node - // version 8 and babel will stop transpiling async/await - // because they are supported in the "current" version of node - node: 'current', - }, +module.exports = () => { + return { + presets: [ + [ + require.resolve('@babel/preset-env'), + { + targets: { + // only applies the necessary transformations based on the + // current node.js processes version. For example: running + // `nvm install 8 && node ./src/cli` will run kibana in node + // version 8 and babel will stop transpiling async/await + // because they are supported in the "current" version of node + node: 'current', + }, - // replaces `import "babel-polyfill"` with a list of require statements - // for just the polyfills that the target versions don't already supply - // on their own - useBuiltIns: true, - }, + // replaces `import "@babel/polyfill"` with a list of require statements + // for just the polyfills that the target versions don't already supply + // on their own + useBuiltIns: 'entry', + modules: 'cjs' + }, + ], + require('./common_preset'), ], - require('./common_preset'), - ], - plugins: [ - [ - require.resolve('babel-plugin-transform-define'), - { - 'global.__BUILT_WITH_BABEL__': 'true' - } + plugins: [ + [ + require.resolve('babel-plugin-transform-define'), + { + 'global.__BUILT_WITH_BABEL__': 'true' + } + ] ] - ] + }; }; diff --git a/packages/kbn-babel-preset/node_preset_7.js b/packages/kbn-babel-preset/node_preset_7.js deleted file mode 100644 index b57dd58dd9f15..0000000000000 --- a/packages/kbn-babel-preset/node_preset_7.js +++ /dev/null @@ -1,50 +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. - */ - -module.exports = () => ({ - presets: [ - [ - require.resolve('@babel/preset-env'), - { - targets: { - // only applies the necessary transformations based on the - // current node.js processes version. For example: running - // `nvm install 8 && node ./src/cli` will run kibana in node - // version 8 and babel will stop transpiling async/await - // because they are supported in the "current" version of node - node: 'current', - }, - - // replaces `import "babel-polyfill"` with a list of require statements - // for just the polyfills that the target versions don't already supply - // on their own - useBuiltIns: 'entry', - }, - ], - require('./common_preset_7'), - ], - plugins: [ - [ - require.resolve('babel-plugin-transform-define'), - { - 'global.__BUILT_WITH_BABEL__': 'true' - } - ] - ] -}); diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json index 41c03c0542675..79ee6bbe39c0c 100644 --- a/packages/kbn-babel-preset/package.json +++ b/packages/kbn-babel-preset/package.json @@ -4,20 +4,12 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@babel/core": "^7.3.4", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-class-properties": "^7.3.4", - "@babel/plugin-proposal-object-rest-spread": "^7.3.4", + "@babel/preset-react":"^7.0.0", "@babel/preset-env": "^7.3.4", - "@babel/preset-react": "^7.0.0", "@babel/preset-typescript": "^7.3.3", - "babel-plugin-add-module-exports": "^0.2.1", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-add-module-exports": "^1.0.0", "babel-plugin-transform-define": "^1.3.1", - "babel-plugin-transform-object-rest-spread": "^6.26.0", - "babel-preset-env": "^1.7.0", - "babel-preset-react": "^6.24.1", - "babel7-plugin-add-module-exports": "npm:babel-plugin-add-module-exports@^1.0.0" + "babel-plugin-typescript-strip-namespaces": "^1.1.1" } } diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js index 97bfa44a049d9..df5745bc33f89 100644 --- a/packages/kbn-babel-preset/webpack_preset.js +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -17,21 +17,24 @@ * under the License. */ -module.exports = { - presets: [ - [ - require.resolve('babel-preset-env'), - { - targets: { - browsers: [ - 'last 2 versions', - '> 5%', - 'Safari 7', // for PhantomJS support: https://github.com/elastic/kibana/issues/27136 - ], +module.exports = () => { + return { + presets: [ + [ + require.resolve('@babel/preset-env'), + { + targets: { + browsers: [ + 'last 2 versions', + '> 5%', + 'Safari 7', // for PhantomJS support: https://github.com/elastic/kibana/issues/27136 + ], + }, + useBuiltIns: 'entry', + modules: 'cjs' }, - useBuiltIns: true, - }, - ], - require('./common_preset'), - ] + ], + require('./common_preset'), + ] + }; }; diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json index af39ffecf6690..4fbc80d6e679a 100644 --- a/packages/kbn-dev-utils/package.json +++ b/packages/kbn-dev-utils/package.json @@ -19,9 +19,9 @@ "tslib": "^1.9.3" }, "devDependencies": { + "@babel/cli": "^7.2.3", "@kbn/babel-preset": "1.0.0", "@kbn/expect": "1.0.0", - "babel-cli": "^6.26.0", "chance": "1.0.6" } } diff --git a/packages/kbn-eslint-plugin-eslint/package.json b/packages/kbn-eslint-plugin-eslint/package.json index b35387384071e..e2024b54a620c 100644 --- a/packages/kbn-eslint-plugin-eslint/package.json +++ b/packages/kbn-eslint-plugin-eslint/package.json @@ -4,8 +4,8 @@ "private": true, "license": "Apache-2.0", "peerDependencies": { - "eslint": "^5.6.0", - "babel-eslint": "^9.0.0" + "eslint": "^5.14.1", + "babel-eslint": "^10.0.1" }, "dependencies": { "dedent": "^0.7.0" diff --git a/packages/kbn-i18n/tsconfig.json b/packages/kbn-i18n/tsconfig.json index 3b757d1240bdc..d3dae3078c1d7 100644 --- a/packages/kbn-i18n/tsconfig.json +++ b/packages/kbn-i18n/tsconfig.json @@ -1,20 +1,20 @@ -{ - "extends": "../../tsconfig.json", - "include": [ - "src/**/*.ts", - "src/**/*.tsx", - "types/intl_format_cache.d.ts", - "types/intl_relativeformat.d.ts" - ], - "exclude": [ - "target" - ], - "compilerOptions": { - "declaration": true, - "declarationDir": "./target/types", - "types": [ - "jest", - "node" - ] - } -} +{ + "extends": "../../tsconfig.json", + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + "types/intl_format_cache.d.ts", + "types/intl_relativeformat.d.ts" + ], + "exclude": [ + "target" + ], + "compilerOptions": { + "declaration": true, + "declarationDir": "./target/types", + "types": [ + "jest", + "node" + ] + } +} diff --git a/packages/kbn-interpreter/.babelrc b/packages/kbn-interpreter/.babelrc index 57a5cc3669eb4..875cbcde9d0e1 100644 --- a/packages/kbn-interpreter/.babelrc +++ b/packages/kbn-interpreter/.babelrc @@ -1,8 +1,7 @@ { "presets": ["@kbn/babel-preset/webpack_preset"], "plugins": [ - ["babel-plugin-transform-runtime", { - "polyfill": false, + ["@babel/plugin-transform-runtime", { "regenerator": true }] ] diff --git a/packages/kbn-interpreter/package.json b/packages/kbn-interpreter/package.json index 290e02cb2b2e7..ded8f38bff492 100644 --- a/packages/kbn-interpreter/package.json +++ b/packages/kbn-interpreter/package.json @@ -9,19 +9,20 @@ "kbn:watch": "node scripts/build --dev --watch" }, "dependencies": { + "@babel/runtime": "^7.3.4", "@kbn/i18n": "1.0.0", "lodash": "npm:@elastic/lodash@3.10.1-kibana1", "lodash.clone": "^4.5.0", "uuid": "3.0.1" }, "devDependencies": { + "@babel/cli": "^7.2.3", + "@babel/core": "7.3.4", + "@babel/plugin-transform-runtime": "^7.3.4", + "@babel/polyfill": "7.2.5", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", - "babel-cli": "^6.26.0", - "babel-core": "6.26.3", - "babel-loader": "7.1.5", - "babel-plugin-transform-runtime": "^6.23.0", - "babel-polyfill": "6.20.0", + "babel-loader": "8.0.5", "copy-webpack-plugin": "^4.6.0", "css-loader": "1.0.0", "del": "^3.0.0", diff --git a/packages/kbn-interpreter/tasks/build/server_code_transformer.js b/packages/kbn-interpreter/tasks/build/server_code_transformer.js index 5db4dc13640cb..b1185f4752196 100644 --- a/packages/kbn-interpreter/tasks/build/server_code_transformer.js +++ b/packages/kbn-interpreter/tasks/build/server_code_transformer.js @@ -19,7 +19,7 @@ const { extname } = require('path'); -const { transform } = require('babel-core'); +const { transform } = require('@babel/core'); exports.createServerCodeTransformer = (sourceMaps) => { return (content, path) => { diff --git a/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js b/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js index 01dc9323352ae..519e529c20bf5 100644 --- a/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js +++ b/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js @@ -28,15 +28,14 @@ describe('js support', () => { it('transpiles js file', () => { const transformer = createServerCodeTransformer(); expect(transformer(JS_FIXTURE, JS_FIXTURE_PATH)).toMatchInlineSnapshot(` -"'use strict'; +"\\"use strict\\"; -var _util = require('util'); - -var _util2 = _interopRequireDefault(_util); +var _util = _interopRequireDefault(require(\\"util\\")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -console.log(_util2.default.format('hello world')); /* eslint-disable */" +/* eslint-disable */ +console.log(_util.default.format('hello world'));" `); }); diff --git a/packages/kbn-plugin-generator/sao_template/template/package_template.json b/packages/kbn-plugin-generator/sao_template/template/package_template.json index 80e6ae8642e15..7a6d0842a1649 100644 --- a/packages/kbn-plugin-generator/sao_template/template/package_template.json +++ b/packages/kbn-plugin-generator/sao_template/template/package_template.json @@ -27,15 +27,15 @@ "@elastic/eslint-import-resolver-kibana": "link:../../kibana/packages/kbn-eslint-import-resolver-kibana", "@kbn/expect": "1.0.0", "@kbn/plugin-helpers": "link:../../kibana/packages/kbn-plugin-helpers", - "babel-eslint": "^9.0.0", - "eslint": "^5.6.0", - "eslint-plugin-babel": "^5.2.0", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-jest": "^21.26.2", - "eslint-plugin-jsx-a11y": "^6.1.2", - "eslint-plugin-mocha": "^5.2.0", + "babel-eslint": "^10.0.1", + "eslint": "^5.14.1", + "eslint-plugin-babel": "^5.3.0", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-jest": "^22.3.0", + "eslint-plugin-jsx-a11y": "^6.2.1", + "eslint-plugin-mocha": "^5.3.0", "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", - "eslint-plugin-react": "^7.11.1" + "eslint-plugin-react": "^7.12.4" } } diff --git a/packages/kbn-plugin-helpers/lib/utils.js b/packages/kbn-plugin-helpers/lib/utils.js index ee82b9a8fd57d..d9a5b9148208f 100644 --- a/packages/kbn-plugin-helpers/lib/utils.js +++ b/packages/kbn-plugin-helpers/lib/utils.js @@ -25,7 +25,7 @@ function babelRegister() { const plugin = pluginConfig(); try { - // add support for moved babel-register source: https://github.com/elastic/kibana/pull/13973 + // add support for moved @babel/register source: https://github.com/elastic/kibana/pull/13973 require(resolve(plugin.kibanaRoot, 'src/setup_node_env/babel_register')); // eslint-disable-line import/no-dynamic-require } catch (error) { if (error.code === 'MODULE_NOT_FOUND') { diff --git a/packages/kbn-pm/.babelrc b/packages/kbn-pm/.babelrc index f34e55f9b7ba6..1ca768097a7ee 100644 --- a/packages/kbn-pm/.babelrc +++ b/packages/kbn-pm/.babelrc @@ -1,10 +1,14 @@ { "presets": [ - "stage-3", - ["env", { + "@babel/typescript", + ["@babel/preset-env", { "targets": { "node": "current" } }] + ], + "plugins": [ + "@babel/proposal-class-properties", + "@babel/proposal-object-rest-spread" ] -} \ No newline at end of file +} diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 5910f00408b17..808f72116f815 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -87,146 +87,90 @@ module.exports = /************************************************************************/ /******/ ([ /* 0 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(367); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); -Object.defineProperty(exports, "__esModule", { - value: true -}); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); -var _cli = __webpack_require__(1); +/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(131); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return _utils_workspaces__WEBPACK_IMPORTED_MODULE_2__["copyWorkspacePackages"]; }); -Object.defineProperty(exports, 'run', { - enumerable: true, - get: function () { - return _cli.run; - } -}); - -var _production = __webpack_require__(367); +/* + * 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. + */ -Object.defineProperty(exports, 'buildProductionProjects', { - enumerable: true, - get: function () { - return _production.buildProductionProjects; - } -}); -Object.defineProperty(exports, 'prepareExternalProjectDependencies', { - enumerable: true, - get: function () { - return _production.prepareExternalProjectDependencies; - } -}); -var _workspaces = __webpack_require__(131); -Object.defineProperty(exports, 'copyWorkspacePackages', { - enumerable: true, - get: function () { - return _workspaces.copyWorkspacePackages; - } -}); /***/ }), /* 1 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "run", function() { return run; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var getopts__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(15); +/* harmony import */ var getopts__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(getopts__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(357); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(33); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.run = undefined; - -let run = exports.run = (() => { - var _ref = _asyncToGenerator(function* (argv) { - // We can simplify this setup (and remove this extra handling) once Yarn - // starts forwarding the `--` directly to this script, see - // https://github.com/yarnpkg/yarn/blob/b2d3e1a8fe45ef376b716d597cc79b38702a9320/src/cli/index.js#L174-L182 - if (argv.includes('--')) { - _log.log.write(_chalk2.default.red(`Using "--" is not allowed, as it doesn't work with 'yarn kbn'.`)); - process.exit(1); - } - const options = (0, _getopts2.default)(argv, { - alias: { - e: 'exclude', - h: 'help', - i: 'include' - }, - boolean: ['prefer-offline', 'frozen-lockfile'] - }); - const args = options._; - if (options.help || args.length === 0) { - help(); - return; - } - // This `rootPath` is relative to `./dist/` as that's the location of the - // built version of this tool. - const rootPath = (0, _path.resolve)(__dirname, '../../../'); - const commandName = args[0]; - const extraArgs = args.slice(1); - const commandOptions = { options, extraArgs, rootPath }; - const command = _commands.commands[commandName]; - if (command === undefined) { - _log.log.write(_chalk2.default.red(`[${commandName}] is not a valid command, see 'kbn --help'`)); - process.exit(1); - } - yield (0, _run.runCommand)(command, commandOptions); - }); - - return function run(_x) { - return _ref.apply(this, arguments); - }; -})(); - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _dedent = __webpack_require__(14); - -var _dedent2 = _interopRequireDefault(_dedent); - -var _getopts = __webpack_require__(15); - -var _getopts2 = _interopRequireDefault(_getopts); - -var _path = __webpack_require__(16); - -var _commands = __webpack_require__(17); -var _run = __webpack_require__(357); -var _log = __webpack_require__(33); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ function help() { - const availableCommands = Object.keys(_commands.commands).map(commandName => _commands.commands[commandName]).map(command => `${command.name} - ${command.description}`); - _log.log.write(_dedent2.default` + const availableCommands = Object.keys(_commands__WEBPACK_IMPORTED_MODULE_4__["commands"]).map(commandName => _commands__WEBPACK_IMPORTED_MODULE_4__["commands"][commandName]).map(command => `${command.name} - ${command.description}`); + _utils_log__WEBPACK_IMPORTED_MODULE_6__["log"].write(dedent__WEBPACK_IMPORTED_MODULE_1___default.a` usage: kbn [] By default commands are run for Kibana itself, all packages in the 'packages/' @@ -245,6 +189,50 @@ function help() { `); } +async function run(argv) { + // We can simplify this setup (and remove this extra handling) once Yarn + // starts forwarding the `--` directly to this script, see + // https://github.com/yarnpkg/yarn/blob/b2d3e1a8fe45ef376b716d597cc79b38702a9320/src/cli/index.js#L174-L182 + if (argv.includes('--')) { + _utils_log__WEBPACK_IMPORTED_MODULE_6__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`Using "--" is not allowed, as it doesn't work with 'yarn kbn'.`)); + process.exit(1); + } + + const options = getopts__WEBPACK_IMPORTED_MODULE_2___default()(argv, { + alias: { + e: 'exclude', + h: 'help', + i: 'include' + }, + boolean: ['prefer-offline', 'frozen-lockfile'] + }); + const args = options._; + + if (options.help || args.length === 0) { + help(); + return; + } // This `rootPath` is relative to `./dist/` as that's the location of the + // built version of this tool. + + + const rootPath = Object(path__WEBPACK_IMPORTED_MODULE_3__["resolve"])(__dirname, '../../../'); + const commandName = args[0]; + const extraArgs = args.slice(1); + const commandOptions = { + options, + extraArgs, + rootPath + }; + const command = _commands__WEBPACK_IMPORTED_MODULE_4__["commands"][commandName]; + + if (command === undefined) { + _utils_log__WEBPACK_IMPORTED_MODULE_6__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`[${commandName}] is not a valid command, see 'kbn --help'`)); + process.exit(1); + } + + await Object(_run__WEBPACK_IMPORTED_MODULE_5__["runCommand"])(command, commandOptions); +} + /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { @@ -2452,24 +2440,15 @@ module.exports = require("path"); /***/ }), /* 17 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.commands = undefined; - -var _bootstrap = __webpack_require__(18); - -var _clean = __webpack_require__(133); - -var _run = __webpack_require__(155); - -var _watch = __webpack_require__(156); - +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); +/* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(133); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(155); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(156); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2488,117 +2467,137 @@ var _watch = __webpack_require__(156); * specific language governing permissions and limitations * under the License. */ -const commands = exports.commands = { - bootstrap: _bootstrap.BootstrapCommand, - clean: _clean.CleanCommand, - run: _run.RunCommand, - watch: _watch.WatchCommand + + + + +const commands = { + bootstrap: _bootstrap__WEBPACK_IMPORTED_MODULE_0__["BootstrapCommand"], + clean: _clean__WEBPACK_IMPORTED_MODULE_1__["CleanCommand"], + run: _run__WEBPACK_IMPORTED_MODULE_2__["RunCommand"], + watch: _watch__WEBPACK_IMPORTED_MODULE_3__["WatchCommand"] }; /***/ }), /* 18 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BootstrapCommand", function() { return BootstrapCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(33); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(34); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(35); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.BootstrapCommand = undefined; - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _link_project_executables = __webpack_require__(19); -var _log = __webpack_require__(33); -var _parallelize = __webpack_require__(34); -var _projects = __webpack_require__(35); +const BootstrapCommand = { + description: 'Install dependencies and crosslink projects', + name: 'bootstrap', -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + async run(projects, projectGraph, { + options + }) { + const batchedProjectsByWorkspace = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_4__["topologicallyBatchProjects"])(projects, projectGraph, { + batchByWorkspace: true + }); + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_4__["topologicallyBatchProjects"])(projects, projectGraph); + const extraArgs = [...(options['frozen-lockfile'] === true ? ['--frozen-lockfile'] : []), ...(options['prefer-offline'] === true ? ['--prefer-offline'] : [])]; + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold('\nRunning installs in topological order:')); + + for (const batch of batchedProjectsByWorkspace) { + for (const project of batch) { + if (project.isWorkspaceProject) { + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(`Skipping workspace project: ${project.name}`); + continue; + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + if (project.hasDependencies()) { + await project.installDependencies({ + extraArgs + }); + } + } + } + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold('\nInstalls completed, linking package executables:\n')); + await Object(_utils_link_project_executables__WEBPACK_IMPORTED_MODULE_1__["linkProjectExecutables"])(projects, projectGraph); + /** + * At the end of the bootstrapping process we call all `kbn:bootstrap` scripts + * in the list of projects. We do this because some projects need to be + * transpiled before they can be used. Ideally we shouldn't do this unless we + * have to, as it will slow down the bootstrapping process. + */ -const BootstrapCommand = exports.BootstrapCommand = { - description: 'Install dependencies and crosslink projects', - name: 'bootstrap', - run(projects, projectGraph, { options }) { - return _asyncToGenerator(function* () { - const batchedProjectsByWorkspace = (0, _projects.topologicallyBatchProjects)(projects, projectGraph, { - batchByWorkspace: true - }); - const batchedProjects = (0, _projects.topologicallyBatchProjects)(projects, projectGraph); - const extraArgs = [...(options['frozen-lockfile'] === true ? ['--frozen-lockfile'] : []), ...(options['prefer-offline'] === true ? ['--prefer-offline'] : [])]; - _log.log.write(_chalk2.default.bold('\nRunning installs in topological order:')); - for (const batch of batchedProjectsByWorkspace) { - for (const project of batch) { - if (project.isWorkspaceProject) { - _log.log.write(`Skipping workspace project: ${project.name}`); - continue; - } - if (project.hasDependencies()) { - yield project.installDependencies({ extraArgs }); - } - } - } - _log.log.write(_chalk2.default.bold('\nInstalls completed, linking package executables:\n')); - yield (0, _link_project_executables.linkProjectExecutables)(projects, projectGraph); - /** - * At the end of the bootstrapping process we call all `kbn:bootstrap` scripts - * in the list of projects. We do this because some projects need to be - * transpiled before they can be used. Ideally we shouldn't do this unless we - * have to, as it will slow down the bootstrapping process. - */ - _log.log.write(_chalk2.default.bold('\nLinking executables completed, running `kbn:bootstrap` scripts\n')); - yield (0, _parallelize.parallelizeBatches)(batchedProjects, (() => { - var _ref = _asyncToGenerator(function* (pkg) { - if (pkg.hasScript('kbn:bootstrap')) { - yield pkg.runScriptStreaming('kbn:bootstrap'); - } - }); + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold('\nLinking executables completed, running `kbn:bootstrap` scripts\n')); + await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_3__["parallelizeBatches"])(batchedProjects, async pkg => { + if (pkg.hasScript('kbn:bootstrap')) { + await pkg.runScriptStreaming('kbn:bootstrap'); + } + }); + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green.bold('\nBootstrapping completed!\n')); + } - return function (_x) { - return _ref.apply(this, arguments); - }; - })()); - _log.log.write(_chalk2.default.green.bold('\nBootstrapping completed!\n')); - })(); - } }; /***/ }), /* 19 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "linkProjectExecutables", function() { return linkProjectExecutables; }); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(20); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(33); +/* + * 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. + */ + + -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.linkProjectExecutables = undefined; /** * Yarn does not link the executables from dependencies that are installed @@ -2608,130 +2607,122 @@ exports.linkProjectExecutables = undefined; * dependencies, and manually linking their executables if defined. The logic * for linking was mostly adapted from lerna: https://github.com/lerna/lerna/blob/1d7eb9eeff65d5a7de64dea73613b1bf6bfa8d57/src/PackageUtilities.js#L348 */ -let linkProjectExecutables = exports.linkProjectExecutables = (() => { - var _ref = _asyncToGenerator(function* (projectsByName, projectGraph) { - for (const [projectName, projectDeps] of projectGraph) { - const project = projectsByName.get(projectName); - const binsDir = (0, _path.resolve)(project.nodeModulesLocation, '.bin'); - for (const projectDep of projectDeps) { - const executables = projectDep.getExecutables(); - for (const name of Object.keys(executables)) { - const srcPath = executables[name]; - // existing logic from lerna -- ensure that the bin we are going to - // point to exists or ignore it - if (!(yield (0, _fs.isFile)(srcPath))) { - continue; - } - const dest = (0, _path.resolve)(binsDir, name); - // Get relative project path with normalized path separators. - const projectRelativePath = (0, _path.relative)(project.path, srcPath).split(_path.sep).join('/'); - _log.log.write(_chalk2.default`{dim [${project.name}]} ${name} -> {dim ${projectRelativePath}}`); - yield (0, _fs.mkdirp)((0, _path.dirname)(dest)); - yield (0, _fs.createSymlink)(srcPath, dest, 'exec'); - yield (0, _fs.chmod)(dest, '755'); - } - } - } - }); - - return function linkProjectExecutables(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); +async function linkProjectExecutables(projectsByName, projectGraph) { + for (const [projectName, projectDeps] of projectGraph) { + const project = projectsByName.get(projectName); + const binsDir = Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(project.nodeModulesLocation, '.bin'); -var _path = __webpack_require__(16); + for (const projectDep of projectDeps) { + const executables = projectDep.getExecutables(); -var _chalk = __webpack_require__(2); + for (const name of Object.keys(executables)) { + const srcPath = executables[name]; // existing logic from lerna -- ensure that the bin we are going to + // point to exists or ignore it -var _chalk2 = _interopRequireDefault(_chalk); - -var _fs = __webpack_require__(20); - -var _log = __webpack_require__(33); + if (!(await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["isFile"])(srcPath))) { + continue; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + const dest = Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(binsDir, name); // Get relative project path with normalized path separators. -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + const projectRelativePath = Object(path__WEBPACK_IMPORTED_MODULE_0__["relative"])(project.path, srcPath).split(path__WEBPACK_IMPORTED_MODULE_0__["sep"]).join('/'); + _log__WEBPACK_IMPORTED_MODULE_3__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_1___default.a`{dim [${project.name}]} ${name} -> {dim ${projectRelativePath}}`); + await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["mkdirp"])(Object(path__WEBPACK_IMPORTED_MODULE_0__["dirname"])(dest)); + await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["createSymlink"])(srcPath, dest, 'exec'); + await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["chmod"])(dest, '755'); + } + } + } +} /***/ }), /* 20 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unlink", function() { return unlink; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "copyDirectory", function() { return copyDirectory; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "chmod", function() { return chmod; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readFile", function() { return readFile; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mkdirp", function() { return mkdirp; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isDirectory", function() { return isDirectory; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isFile", function() { return isFile; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createSymlink", function() { return createSymlink; }); +/* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(21); +/* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cmd_shim__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(23); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var mkdirp__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(31); +/* harmony import */ var mkdirp__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(mkdirp__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(32); +/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ncp__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(29); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_5__); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createSymlink = exports.isFile = exports.isDirectory = exports.mkdirp = exports.readFile = exports.chmod = exports.copyDirectory = exports.unlink = undefined; -let statTest = (() => { - var _ref = _asyncToGenerator(function* (path, block) { - try { - return block((yield stat(path))); - } catch (e) { - if (e.code === 'ENOENT') { - return false; - } - throw e; - } - }); - return function statTest(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); + + +const stat = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.stat); +const readFile = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.readFile); +const symlink = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.symlink); +const chmod = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.chmod); +const cmdShim = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(cmd_shim__WEBPACK_IMPORTED_MODULE_0___default.a); +const mkdirp = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(mkdirp__WEBPACK_IMPORTED_MODULE_2___default.a); +const unlink = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.unlink); +const copyDirectory = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(ncp__WEBPACK_IMPORTED_MODULE_3__["ncp"]); + + +async function statTest(path, block) { + try { + return block((await stat(path))); + } catch (e) { + if (e.code === 'ENOENT') { + return false; + } + + throw e; + } +} /** * Test if a path points to a directory. * @param path */ -let isDirectory = exports.isDirectory = (() => { - var _ref2 = _asyncToGenerator(function* (path) { - return yield statTest(path, function (stats) { - return stats.isDirectory(); - }); - }); - - return function isDirectory(_x3) { - return _ref2.apply(this, arguments); - }; -})(); +async function isDirectory(path) { + return await statTest(path, stats => stats.isDirectory()); +} /** * Test if a path points to a regular file. * @param path */ - -let isFile = exports.isFile = (() => { - var _ref3 = _asyncToGenerator(function* (path) { - return yield statTest(path, function (stats) { - return stats.isFile(); - }); - }); - - return function isFile(_x4) { - return _ref3.apply(this, arguments); - }; -})(); +async function isFile(path) { + return await statTest(path, stats => stats.isFile()); +} /** * Create a symlink at dest that points to src. Adapted from * https://github.com/lerna/lerna/blob/2f1b87d9e2295f587e4ac74269f714271d8ed428/src/FileSystemUtilities.js#L103. @@ -2743,96 +2734,32 @@ let isFile = exports.isFile = (() => { * for executable files on windows. */ +async function createSymlink(src, dest, type) { + if (process.platform === 'win32') { + if (type === 'exec') { + await cmdShim(src, dest); + } else { + await forceCreate(src, dest, type); + } + } else { + const posixType = type === 'exec' ? 'file' : type; + const relativeSource = Object(path__WEBPACK_IMPORTED_MODULE_4__["relative"])(Object(path__WEBPACK_IMPORTED_MODULE_4__["dirname"])(dest), src); + await forceCreate(relativeSource, dest, posixType); + } +} -let createSymlink = exports.createSymlink = (() => { - var _ref4 = _asyncToGenerator(function* (src, dest, type) { - if (process.platform === 'win32') { - if (type === 'exec') { - yield cmdShim(src, dest); - } else { - yield forceCreate(src, dest, type); - } - } else { - const posixType = type === 'exec' ? 'file' : type; - const relativeSource = (0, _path.relative)((0, _path.dirname)(dest), src); - yield forceCreate(relativeSource, dest, posixType); - } - }); - - return function createSymlink(_x5, _x6, _x7) { - return _ref4.apply(this, arguments); - }; -})(); - -let forceCreate = (() => { - var _ref5 = _asyncToGenerator(function* (src, dest, type) { - try { - // If something exists at `dest` we need to remove it first. - yield unlink(dest); - } catch (error) { - if (error.code !== 'ENOENT') { - throw error; - } - } - yield symlink(src, dest, type); - }); - - return function forceCreate(_x8, _x9, _x10) { - return _ref5.apply(this, arguments); - }; -})(); - -var _cmdShim = __webpack_require__(21); - -var _cmdShim2 = _interopRequireDefault(_cmdShim); - -var _fs = __webpack_require__(23); - -var _fs2 = _interopRequireDefault(_fs); - -var _mkdirp = __webpack_require__(31); - -var _mkdirp2 = _interopRequireDefault(_mkdirp); - -var _ncp = __webpack_require__(32); - -var _path = __webpack_require__(16); - -var _util = __webpack_require__(29); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ - +async function forceCreate(src, dest, type) { + try { + // If something exists at `dest` we need to remove it first. + await unlink(dest); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } -const stat = (0, _util.promisify)(_fs2.default.stat); -const readFile = (0, _util.promisify)(_fs2.default.readFile); -const symlink = (0, _util.promisify)(_fs2.default.symlink); -const chmod = (0, _util.promisify)(_fs2.default.chmod); -const cmdShim = (0, _util.promisify)(_cmdShim2.default); -const mkdirp = (0, _util.promisify)(_mkdirp2.default); -const unlink = exports.unlink = (0, _util.promisify)(_fs2.default.unlink); -const copyDirectory = exports.copyDirectory = (0, _util.promisify)(_ncp.ncp); -exports.chmod = chmod; -exports.readFile = readFile; -exports.mkdirp = mkdirp; + await symlink(src, dest, type); +} /***/ }), /* 21 */ @@ -4179,14 +4106,11 @@ function ncp (source, dest, options, callback) { /***/ }), /* 33 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "log", function() { return log; }); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -4205,7 +4129,7 @@ Object.defineProperty(exports, "__esModule", { * specific language governing permissions and limitations * under the License. */ -const log = exports.log = { +const log = { /** * Log something to the console. Ideally we would use a real logger in * kbn-pm, but that's a pretty big change for now. @@ -4215,19 +4139,94 @@ const log = exports.log = { // tslint:disable no-console console.log(...args); } + }; /***/ }), /* 34 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parallelizeBatches", function() { return parallelizeBatches; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parallelize", function() { return parallelize; }); +/* + * 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. + */ +async function parallelizeBatches(batches, fn) { + for (const batch of batches) { + // We need to make sure the entire batch has completed before we can move on + // to the next batch + await parallelize(batch, fn); + } +} +async function parallelize(items, fn, concurrency = 4) { + if (items.length === 0) { + return; + } + return new Promise((resolve, reject) => { + let activePromises = 0; + const values = items.slice(0); -Object.defineProperty(exports, "__esModule", { - value: true -}); + async function scheduleItem(item) { + activePromises++; + try { + await fn(item); + activePromises--; + + if (values.length > 0) { + // We have more work to do, so we schedule the next promise + scheduleItem(values.shift()); + } else if (activePromises === 0) { + // We have no more values left, and all items have completed, so we've + // completed all the work. + resolve(); + } + } catch (error) { + reject(error); + } + } + + values.splice(0, concurrency).map(scheduleItem); + }); +} + +/***/ }), +/* 35 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getProjects", function() { return getProjects; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProjectGraph", function() { return buildProjectGraph; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "topologicallyBatchProjects", function() { return topologicallyBatchProjects; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "includeTransitiveProjects", function() { return includeTransitiveProjects; }); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(52); +/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(53); +/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(131); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -4246,252 +4245,181 @@ Object.defineProperty(exports, "__esModule", { * specific language governing permissions and limitations * under the License. */ -let parallelizeBatches = exports.parallelizeBatches = (() => { - var _ref = _asyncToGenerator(function* (batches, fn) { - for (const batch of batches) { - // We need to make sure the entire batch has completed before we can move on - // to the next batch - yield parallelize(batch, fn); - } + + + + + + +const glob = Object(util__WEBPACK_IMPORTED_MODULE_2__["promisify"])(glob__WEBPACK_IMPORTED_MODULE_0___default.a); +async function getProjects(rootPath, projectsPathsPatterns, { + include = [], + exclude = [] +} = {}) { + const projects = new Map(); + const workspaceProjectsPaths = await Object(_workspaces__WEBPACK_IMPORTED_MODULE_5__["workspacePackagePaths"])(rootPath); + + for (const pattern of projectsPathsPatterns) { + const pathsToProcess = await packagesFromGlobPattern({ + pattern, + rootPath }); - return function parallelizeBatches(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); + for (const filePath of pathsToProcess) { + const projectConfigPath = normalize(filePath); + const projectDir = path__WEBPACK_IMPORTED_MODULE_1___default.a.dirname(projectConfigPath); + const project = await _project__WEBPACK_IMPORTED_MODULE_4__["Project"].fromPath(projectDir); -let parallelize = exports.parallelize = (() => { - var _ref2 = _asyncToGenerator(function* (items, fn, concurrency = 4) { - if (items.length === 0) { - return; - } - return new Promise(function (resolve, reject) { - let scheduleItem = (() => { - var _ref3 = _asyncToGenerator(function* (item) { - activePromises++; - try { - yield fn(item); - activePromises--; - if (values.length > 0) { - // We have more work to do, so we schedule the next promise - scheduleItem(values.shift()); - } else if (activePromises === 0) { - // We have no more values left, and all items have completed, so we've - // completed all the work. - resolve(); - } - } catch (error) { - reject(error); - } - }); + if (workspaceProjectsPaths.indexOf(filePath) >= 0) { + project.isWorkspaceProject = true; + } - return function scheduleItem(_x5) { - return _ref3.apply(this, arguments); - }; - })(); + const excludeProject = exclude.includes(project.name) || include.length > 0 && !include.includes(project.name); - let activePromises = 0; - const values = items.slice(0); + if (excludeProject) { + continue; + } - values.splice(0, concurrency).map(scheduleItem); + if (projects.has(project.name)) { + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](`There are multiple projects with the same name [${project.name}]`, { + name: project.name, + paths: [project.path, projects.get(project.name).path] }); - }); + } - return function parallelize(_x3, _x4) { - return _ref2.apply(this, arguments); - }; -})(); + projects.set(project.name, project); + } + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + return projects; +} -/***/ }), -/* 35 */ -/***/ (function(module, exports, __webpack_require__) { +function packagesFromGlobPattern({ + pattern, + rootPath +}) { + const globOptions = { + cwd: rootPath, + // Should throw in case of unusual errors when reading the file system + strict: true, + // Always returns absolute paths for matched files + absolute: true, + // Do not match ** against multiple filenames + // (This is only specified because we currently don't have a need for it.) + noglobstar: true + }; + return glob(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(pattern, 'package.json'), globOptions); +} // https://github.com/isaacs/node-glob/blob/master/common.js#L104 +// glob always returns "\\" as "/" in windows, so everyone +// gets normalized because we can't have nice things. -"use strict"; +function normalize(dir) { + return path__WEBPACK_IMPORTED_MODULE_1___default.a.normalize(dir); +} -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getProjects = undefined; - -let getProjects = exports.getProjects = (() => { - var _ref = _asyncToGenerator(function* (rootPath, projectsPathsPatterns, { include = [], exclude = [] } = {}) { - const projects = new Map(); - const workspaceProjectsPaths = yield (0, _workspaces.workspacePackagePaths)(rootPath); - for (const pattern of projectsPathsPatterns) { - const pathsToProcess = yield packagesFromGlobPattern({ pattern, rootPath }); - for (const filePath of pathsToProcess) { - const projectConfigPath = normalize(filePath); - const projectDir = _path2.default.dirname(projectConfigPath); - const project = yield _project.Project.fromPath(projectDir); - if (workspaceProjectsPaths.indexOf(filePath) >= 0) { - project.isWorkspaceProject = true; - } - const excludeProject = exclude.includes(project.name) || include.length > 0 && !include.includes(project.name); - if (excludeProject) { - continue; - } - if (projects.has(project.name)) { - throw new _errors.CliError(`There are multiple projects with the same name [${project.name}]`, { - name: project.name, - paths: [project.path, projects.get(project.name).path] - }); - } - projects.set(project.name, project); - } - } - return projects; - }); +function buildProjectGraph(projects) { + const projectGraph = new Map(); - return function getProjects(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); + for (const project of projects.values()) { + const projectDeps = []; + const dependencies = project.allDependencies; -exports.buildProjectGraph = buildProjectGraph; -exports.topologicallyBatchProjects = topologicallyBatchProjects; -exports.includeTransitiveProjects = includeTransitiveProjects; + for (const depName of Object.keys(dependencies)) { + if (projects.has(depName)) { + const dep = projects.get(depName); + const dependentProjectIsInWorkspace = project.isWorkspaceProject || project.json.name === 'kibana'; + project.ensureValidProjectDependency(dep, dependentProjectIsInWorkspace); + projectDeps.push(dep); + } + } -var _glob = __webpack_require__(36); + projectGraph.set(project.name, projectDeps); + } -var _glob2 = _interopRequireDefault(_glob); + return projectGraph; +} +function topologicallyBatchProjects(projectsToBatch, projectGraph, { + batchByWorkspace = false +} = {}) { + // We're going to be chopping stuff out of this list, so copy it. + const projectsLeftToBatch = new Set(projectsToBatch.keys()); + const batches = []; -var _path = __webpack_require__(16); + if (batchByWorkspace) { + const workspaceRootProject = Array.from(projectsToBatch.values()).find(p => p.isWorkspaceRoot); -var _path2 = _interopRequireDefault(_path); + if (!workspaceRootProject) { + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](`There was no yarn workspace root found.`); + } // Push in the workspace root first. -var _util = __webpack_require__(29); -var _errors = __webpack_require__(52); + batches.push([workspaceRootProject]); + projectsLeftToBatch.delete(workspaceRootProject.name); // In the next batch, push in all workspace projects. -var _project = __webpack_require__(53); + const workspaceBatch = []; -var _workspaces = __webpack_require__(131); + for (const projectName of projectsLeftToBatch) { + const project = projectsToBatch.get(projectName); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + if (project.isWorkspaceProject) { + workspaceBatch.push(project); + projectsLeftToBatch.delete(projectName); + } + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + batches.push(workspaceBatch); + } + while (projectsLeftToBatch.size > 0) { + // Get all projects that have no remaining dependencies within the repo + // that haven't yet been picked. + const batch = []; -const glob = (0, _util.promisify)(_glob2.default); + for (const projectName of projectsLeftToBatch) { + const projectDeps = projectGraph.get(projectName); + const needsDependenciesBatched = projectDeps.some(dep => projectsLeftToBatch.has(dep.name)); -function packagesFromGlobPattern({ pattern, rootPath }) { - const globOptions = { - cwd: rootPath, - // Should throw in case of unusual errors when reading the file system - strict: true, - // Always returns absolute paths for matched files - absolute: true, - // Do not match ** against multiple filenames - // (This is only specified because we currently don't have a need for it.) - noglobstar: true - }; - return glob(_path2.default.join(pattern, 'package.json'), globOptions); -} -// https://github.com/isaacs/node-glob/blob/master/common.js#L104 -// glob always returns "\\" as "/" in windows, so everyone -// gets normalized because we can't have nice things. -function normalize(dir) { - return _path2.default.normalize(dir); -} -function buildProjectGraph(projects) { - const projectGraph = new Map(); - for (const project of projects.values()) { - const projectDeps = []; - const dependencies = project.allDependencies; - for (const depName of Object.keys(dependencies)) { - if (projects.has(depName)) { - const dep = projects.get(depName); - const dependentProjectIsInWorkspace = project.isWorkspaceProject || project.json.name === 'kibana'; - project.ensureValidProjectDependency(dep, dependentProjectIsInWorkspace); - projectDeps.push(dep); - } - } - projectGraph.set(project.name, projectDeps); - } - return projectGraph; -} -function topologicallyBatchProjects(projectsToBatch, projectGraph, { batchByWorkspace = false } = {}) { - // We're going to be chopping stuff out of this list, so copy it. - const projectsLeftToBatch = new Set(projectsToBatch.keys()); - const batches = []; - if (batchByWorkspace) { - const workspaceRootProject = Array.from(projectsToBatch.values()).find(p => p.isWorkspaceRoot); - if (!workspaceRootProject) { - throw new _errors.CliError(`There was no yarn workspace root found.`); - } - // Push in the workspace root first. - batches.push([workspaceRootProject]); - projectsLeftToBatch.delete(workspaceRootProject.name); - // In the next batch, push in all workspace projects. - const workspaceBatch = []; - for (const projectName of projectsLeftToBatch) { - const project = projectsToBatch.get(projectName); - if (project.isWorkspaceProject) { - workspaceBatch.push(project); - projectsLeftToBatch.delete(projectName); - } - } - batches.push(workspaceBatch); - } - while (projectsLeftToBatch.size > 0) { - // Get all projects that have no remaining dependencies within the repo - // that haven't yet been picked. - const batch = []; - for (const projectName of projectsLeftToBatch) { - const projectDeps = projectGraph.get(projectName); - const needsDependenciesBatched = projectDeps.some(dep => projectsLeftToBatch.has(dep.name)); - if (!needsDependenciesBatched) { - batch.push(projectsToBatch.get(projectName)); - } - } - // If we weren't able to find a project with no remaining dependencies, - // then we've encountered a cycle in the dependency graph. - const hasCycles = batch.length === 0; - if (hasCycles) { - const cycleProjectNames = [...projectsLeftToBatch]; - const message = 'Encountered a cycle in the dependency graph. Projects in cycle are:\n' + cycleProjectNames.join(', '); - throw new _errors.CliError(message); - } - batches.push(batch); - batch.forEach(project => projectsLeftToBatch.delete(project.name)); - } - return batches; -} -function includeTransitiveProjects(subsetOfProjects, allProjects, { onlyProductionDependencies = false } = {}) { - const dependentProjects = new Map(); - // the current list of packages we are expanding using breadth-first-search - const toProcess = [...subsetOfProjects]; - while (toProcess.length > 0) { - const project = toProcess.shift(); - const dependencies = onlyProductionDependencies ? project.productionDependencies : project.allDependencies; - Object.keys(dependencies).forEach(dep => { - if (allProjects.has(dep)) { - toProcess.push(allProjects.get(dep)); - } - }); - dependentProjects.set(project.name, project); + if (!needsDependenciesBatched) { + batch.push(projectsToBatch.get(projectName)); + } + } // If we weren't able to find a project with no remaining dependencies, + // then we've encountered a cycle in the dependency graph. + + + const hasCycles = batch.length === 0; + + if (hasCycles) { + const cycleProjectNames = [...projectsLeftToBatch]; + const message = 'Encountered a cycle in the dependency graph. Projects in cycle are:\n' + cycleProjectNames.join(', '); + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](message); } - return dependentProjects; + + batches.push(batch); + batch.forEach(project => projectsLeftToBatch.delete(project.name)); + } + + return batches; +} +function includeTransitiveProjects(subsetOfProjects, allProjects, { + onlyProductionDependencies = false +} = {}) { + const dependentProjects = new Map(); // the current list of packages we are expanding using breadth-first-search + + const toProcess = [...subsetOfProjects]; + + while (toProcess.length > 0) { + const project = toProcess.shift(); + const dependencies = onlyProductionDependencies ? project.productionDependencies : project.allDependencies; + Object.keys(dependencies).forEach(dep => { + if (allProjects.has(dep)) { + toProcess.push(allProjects.get(dep)); + } + }); + dependentProjects.set(project.name, project); + } + + return dependentProjects; } /***/ }), @@ -7854,14 +7782,11 @@ function onceStrict (fn) { /***/ }), /* 52 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CliError", function() { return CliError; }); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -7881,208 +7806,227 @@ Object.defineProperty(exports, "__esModule", { * under the License. */ class CliError extends Error { - constructor(message, meta = {}) { - super(message); - this.meta = meta; - } + constructor(message, meta = {}) { + super(message); + this.meta = meta; + } + } -exports.CliError = CliError; /***/ }), /* 53 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return Project; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(52); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(33); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(54); +/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(92); +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Project = undefined; -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* - * 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. - */ -var _chalk = __webpack_require__(2); -var _chalk2 = _interopRequireDefault(_chalk); -var _path = __webpack_require__(16); -var _util = __webpack_require__(29); +class Project { + static async fromPath(path) { + const pkgJson = await Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["readPackageJson"])(path); + return new Project(pkgJson, path); + } -var _errors = __webpack_require__(52); + constructor(packageJson, projectPath) { + _defineProperty(this, "json", void 0); -var _log = __webpack_require__(33); + _defineProperty(this, "packageJsonLocation", void 0); -var _package_json = __webpack_require__(54); + _defineProperty(this, "nodeModulesLocation", void 0); -var _scripts = __webpack_require__(92); + _defineProperty(this, "targetLocation", void 0); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + _defineProperty(this, "path", void 0); -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + _defineProperty(this, "allDependencies", void 0); -class Project { - constructor(packageJson, projectPath) { - this.isWorkspaceRoot = false; - this.isWorkspaceProject = false; - this.json = Object.freeze(packageJson); - this.path = projectPath; - this.packageJsonLocation = (0, _path.resolve)(this.path, 'package.json'); - this.nodeModulesLocation = (0, _path.resolve)(this.path, 'node_modules'); - this.targetLocation = (0, _path.resolve)(this.path, 'target'); - this.productionDependencies = this.json.dependencies || {}; - this.devDependencies = this.json.devDependencies || {}; - this.allDependencies = _extends({}, this.devDependencies, this.productionDependencies); - this.isWorkspaceRoot = this.json.hasOwnProperty('workspaces'); - this.scripts = this.json.scripts || {}; - } - static fromPath(path) { - return _asyncToGenerator(function* () { - const pkgJson = yield (0, _package_json.readPackageJson)(path); - return new Project(pkgJson, path); - })(); - } - get name() { - return this.json.name; - } - ensureValidProjectDependency(project, dependentProjectIsInWorkspace) { - const versionInPackageJson = this.allDependencies[project.name]; - let expectedVersionInPackageJson; - if (dependentProjectIsInWorkspace) { - expectedVersionInPackageJson = project.json.version; - } else { - const relativePathToProject = normalizePath((0, _path.relative)(this.path, project.path)); - expectedVersionInPackageJson = `link:${relativePathToProject}`; - } - // No issues! - if (versionInPackageJson === expectedVersionInPackageJson) { - return; - } - let problemMsg; - if ((0, _package_json.isLinkDependency)(versionInPackageJson) && dependentProjectIsInWorkspace) { - problemMsg = `but should be using a workspace`; - } else if ((0, _package_json.isLinkDependency)(versionInPackageJson)) { - problemMsg = `using 'link:', but the path is wrong`; - } else { - problemMsg = `but it's not using the local package`; - } - throw new _errors.CliError(`[${this.name}] depends on [${project.name}] ${problemMsg}. Update its package.json to the expected value below.`, { - actual: `"${project.name}": "${versionInPackageJson}"`, - expected: `"${project.name}": "${expectedVersionInPackageJson}"`, - package: `${this.name} (${this.packageJsonLocation})` - }); - } - getBuildConfig() { - return this.json.kibana && this.json.kibana.build || {}; - } - /** - * Returns the directory that should be copied into the Kibana build artifact. - * This config can be specified to only include the project's build artifacts - * instead of everything located in the project directory. - */ - getIntermediateBuildDirectory() { - return (0, _path.resolve)(this.path, this.getBuildConfig().intermediateBuildDirectory || '.'); - } - getCleanConfig() { - return this.json.kibana && this.json.kibana.clean || {}; - } - hasScript(name) { - return name in this.scripts; - } - getExecutables() { - const raw = this.json.bin; - if (!raw) { - return {}; - } - if (typeof raw === 'string') { - return { - [this.name]: (0, _path.resolve)(this.path, raw) - }; - } - if (typeof raw === 'object') { - const binsConfig = {}; - for (const binName of Object.keys(raw)) { - binsConfig[binName] = (0, _path.resolve)(this.path, raw[binName]); - } - return binsConfig; - } - throw new _errors.CliError(`[${this.name}] has an invalid "bin" field in its package.json, ` + `expected an object or a string`, { - binConfig: (0, _util.inspect)(raw), - package: `${this.name} (${this.packageJsonLocation})` - }); - } - runScript(scriptName, args = []) { - var _this = this; + _defineProperty(this, "productionDependencies", void 0); + + _defineProperty(this, "devDependencies", void 0); + + _defineProperty(this, "scripts", void 0); + + _defineProperty(this, "isWorkspaceRoot", false); + + _defineProperty(this, "isWorkspaceProject", false); + + this.json = Object.freeze(packageJson); + this.path = projectPath; + this.packageJsonLocation = Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, 'package.json'); + this.nodeModulesLocation = Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, 'node_modules'); + this.targetLocation = Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, 'target'); + this.productionDependencies = this.json.dependencies || {}; + this.devDependencies = this.json.devDependencies || {}; + this.allDependencies = _objectSpread({}, this.devDependencies, this.productionDependencies); + this.isWorkspaceRoot = this.json.hasOwnProperty('workspaces'); + this.scripts = this.json.scripts || {}; + } + + get name() { + return this.json.name; + } + + ensureValidProjectDependency(project, dependentProjectIsInWorkspace) { + const versionInPackageJson = this.allDependencies[project.name]; + let expectedVersionInPackageJson; - return _asyncToGenerator(function* () { - _log.log.write(_chalk2.default.bold(`\n\nRunning script [${_chalk2.default.green(scriptName)}] in [${_chalk2.default.green(_this.name)}]:\n`)); - return (0, _scripts.runScriptInPackage)(scriptName, args, _this); - })(); + if (dependentProjectIsInWorkspace) { + expectedVersionInPackageJson = project.json.version; + } else { + const relativePathToProject = normalizePath(Object(path__WEBPACK_IMPORTED_MODULE_1__["relative"])(this.path, project.path)); + expectedVersionInPackageJson = `link:${relativePathToProject}`; + } // No issues! + + + if (versionInPackageJson === expectedVersionInPackageJson) { + return; } - runScriptStreaming(scriptName, args = []) { - return (0, _scripts.runScriptInPackageStreaming)(scriptName, args, this); + + let problemMsg; + + if (Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["isLinkDependency"])(versionInPackageJson) && dependentProjectIsInWorkspace) { + problemMsg = `but should be using a workspace`; + } else if (Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["isLinkDependency"])(versionInPackageJson)) { + problemMsg = `using 'link:', but the path is wrong`; + } else { + problemMsg = `but it's not using the local package`; } - hasDependencies() { - return Object.keys(this.allDependencies).length > 0; + + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](`[${this.name}] depends on [${project.name}] ${problemMsg}. Update its package.json to the expected value below.`, { + actual: `"${project.name}": "${versionInPackageJson}"`, + expected: `"${project.name}": "${expectedVersionInPackageJson}"`, + package: `${this.name} (${this.packageJsonLocation})` + }); + } + + getBuildConfig() { + return this.json.kibana && this.json.kibana.build || {}; + } + /** + * Returns the directory that should be copied into the Kibana build artifact. + * This config can be specified to only include the project's build artifacts + * instead of everything located in the project directory. + */ + + + getIntermediateBuildDirectory() { + return Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, this.getBuildConfig().intermediateBuildDirectory || '.'); + } + + getCleanConfig() { + return this.json.kibana && this.json.kibana.clean || {}; + } + + hasScript(name) { + return name in this.scripts; + } + + getExecutables() { + const raw = this.json.bin; + + if (!raw) { + return {}; } - installDependencies({ extraArgs }) { - var _this2 = this; - return _asyncToGenerator(function* () { - _log.log.write(_chalk2.default.bold(`\n\nInstalling dependencies in [${_chalk2.default.green(_this2.name)}]:\n`)); - return (0, _scripts.installInDir)(_this2.path, extraArgs); - })(); + if (typeof raw === 'string') { + return { + [this.name]: Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, raw) + }; } -} -exports.Project = Project; // We normalize all path separators to `/` in generated files -function normalizePath(path) { - return path.replace(/[\\\/]+/g, '/'); -} + if (typeof raw === 'object') { + const binsConfig = {}; -/***/ }), -/* 54 */ -/***/ (function(module, exports, __webpack_require__) { + for (const binName of Object.keys(raw)) { + binsConfig[binName] = Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, raw[binName]); + } -"use strict"; + return binsConfig; + } + + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](`[${this.name}] has an invalid "bin" field in its package.json, ` + `expected an object or a string`, { + binConfig: Object(util__WEBPACK_IMPORTED_MODULE_2__["inspect"])(raw), + package: `${this.name} (${this.packageJsonLocation})` + }); + } + async runScript(scriptName, args = []) { + _log__WEBPACK_IMPORTED_MODULE_4__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`\n\nRunning script [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(scriptName)}] in [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(this.name)}]:\n`)); + return Object(_scripts__WEBPACK_IMPORTED_MODULE_6__["runScriptInPackage"])(scriptName, args, this); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isLinkDependency = undefined; -exports.readPackageJson = readPackageJson; -exports.writePackageJson = writePackageJson; + runScriptStreaming(scriptName, args = []) { + return Object(_scripts__WEBPACK_IMPORTED_MODULE_6__["runScriptInPackageStreaming"])(scriptName, args, this); + } -var _readPkg = __webpack_require__(55); + hasDependencies() { + return Object.keys(this.allDependencies).length > 0; + } -var _readPkg2 = _interopRequireDefault(_readPkg); + async installDependencies({ + extraArgs + }) { + _log__WEBPACK_IMPORTED_MODULE_4__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`\n\nInstalling dependencies in [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(this.name)}]:\n`)); + return Object(_scripts__WEBPACK_IMPORTED_MODULE_6__["installInDir"])(this.path, extraArgs); + } -var _writePkg = __webpack_require__(82); +} // We normalize all path separators to `/` in generated files -var _writePkg2 = _interopRequireDefault(_writePkg); +function normalizePath(path) { + return path.replace(/[\\\/]+/g, '/'); +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +/***/ }), +/* 54 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readPackageJson", function() { return readPackageJson; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "writePackageJson", function() { return writePackageJson; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isLinkDependency", function() { return isLinkDependency; }); +/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); +/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(read_pkg__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(82); +/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(write_pkg__WEBPACK_IMPORTED_MODULE_1__); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -8101,13 +8045,17 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de * specific language governing permissions and limitations * under the License. */ + + function readPackageJson(dir) { - return (0, _readPkg2.default)(dir, { normalize: false }); + return read_pkg__WEBPACK_IMPORTED_MODULE_0___default()(dir, { + normalize: false + }); } function writePackageJson(path, json) { - return (0, _writePkg2.default)(path, json); + return write_pkg__WEBPACK_IMPORTED_MODULE_1___default()(path, json); } -const isLinkDependency = exports.isLinkDependency = depVersion => depVersion.startsWith('link:'); +const isLinkDependency = depVersion => depVersion.startsWith('link:'); /***/ }), /* 55 */ @@ -13496,165 +13444,141 @@ module.exports = str => { /***/ }), /* 92 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "installInDir", function() { return installInDir; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackage", function() { return runScriptInPackage; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackageStreaming", function() { return runScriptInPackageStreaming; }); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(93); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.runScriptInPackage = exports.installInDir = undefined; - /** * Install all dependencies in the given directory */ -let installInDir = exports.installInDir = (() => { - var _ref = _asyncToGenerator(function* (directory, extraArgs = []) { - const options = ['install', '--non-interactive', ...extraArgs]; - // We pass the mutex flag to ensure only one instance of yarn runs at any - // given time (e.g. to avoid conflicts). - yield (0, _child_process.spawn)('yarn', options, { - cwd: directory - }); - }); +async function installInDir(directory, extraArgs = []) { + const options = ['install', '--non-interactive', ...extraArgs]; // We pass the mutex flag to ensure only one instance of yarn runs at any + // given time (e.g. to avoid conflicts). - return function installInDir(_x) { - return _ref.apply(this, arguments); - }; -})(); + await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', options, { + cwd: directory + }); +} /** * Run script in the given directory */ - -let runScriptInPackage = exports.runScriptInPackage = (() => { - var _ref2 = _asyncToGenerator(function* (script, args, pkg) { - const execOpts = { - cwd: pkg.path - }; - yield (0, _child_process.spawn)('yarn', ['run', script, ...args], execOpts); - }); - - return function runScriptInPackage(_x2, _x3, _x4) { - return _ref2.apply(this, arguments); - }; -})(); +async function runScriptInPackage(script, args, pkg) { + const execOpts = { + cwd: pkg.path + }; + await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', ['run', script, ...args], execOpts); +} /** * Run script in the given directory */ - -exports.runScriptInPackageStreaming = runScriptInPackageStreaming; - -var _child_process = __webpack_require__(93); - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ - - function runScriptInPackageStreaming(script, args, pkg) { - const execOpts = { - cwd: pkg.path - }; - return (0, _child_process.spawnStreaming)('yarn', ['run', script, ...args], execOpts, { - prefix: pkg.name - }); + const execOpts = { + cwd: pkg.path + }; + return Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawnStreaming"])('yarn', ['run', script, ...args], execOpts, { + prefix: pkg.name + }); } /***/ }), /* 93 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "spawn", function() { return spawn; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "spawnStreaming", function() { return spawnStreaming; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(94); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(122); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(123); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* - * 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. - */ - - -exports.spawn = spawn; -exports.spawnStreaming = spawnStreaming; - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _execa = __webpack_require__(94); - -var _execa2 = _interopRequireDefault(_execa); - -var _logSymbols = __webpack_require__(122); - -var _logSymbols2 = _interopRequireDefault(_logSymbols); -var _strongLogTransformer = __webpack_require__(123); -var _strongLogTransformer2 = _interopRequireDefault(_strongLogTransformer); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function generateColors() { - const colorWheel = [_chalk2.default.cyan, _chalk2.default.magenta, _chalk2.default.blue, _chalk2.default.yellow, _chalk2.default.green]; - const count = colorWheel.length; - let children = 0; - return () => colorWheel[children++ % count]; + const colorWheel = [chalk__WEBPACK_IMPORTED_MODULE_0___default.a.cyan, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.magenta, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.blue, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.yellow, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green]; + const count = colorWheel.length; + let children = 0; + return () => colorWheel[children++ % count]; } + function spawn(command, args, opts) { - return (0, _execa2.default)(command, args, _extends({}, opts, { - stdio: 'inherit' - })); + return execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({}, opts, { + stdio: 'inherit' + })); } const nextColor = generateColors(); -function spawnStreaming(command, args, opts, { prefix }) { - const spawned = (0, _execa2.default)(command, args, _extends({}, opts, { - stdio: ['ignore', 'pipe', 'pipe'] - })); - const color = nextColor(); - const prefixedStdout = (0, _strongLogTransformer2.default)({ tag: `${color.bold(prefix)}:` }); - const prefixedStderr = (0, _strongLogTransformer2.default)({ - mergeMultiline: true, - tag: `${_logSymbols2.default.error} ${color.bold(prefix)}:` - }); - spawned.stdout.pipe(prefixedStdout).pipe(process.stdout); - spawned.stderr.pipe(prefixedStderr).pipe(process.stderr); - return spawned; +function spawnStreaming(command, args, opts, { + prefix +}) { + const spawned = execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({}, opts, { + stdio: ['ignore', 'pipe', 'pipe'] + })); + const color = nextColor(); + const prefixedStdout = strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default()({ + tag: `${color.bold(prefix)}:` + }); + const prefixedStderr = strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default()({ + mergeMultiline: true, + tag: `${log_symbols__WEBPACK_IMPORTED_MODULE_2___default.a.error} ${color.bold(prefix)}:` + }); + spawned.stdout.pipe(prefixedStdout).pipe(process.stdout); + spawned.stderr.pipe(prefixedStderr).pipe(process.stderr); + return spawned; } /***/ }), @@ -17429,306 +17353,290 @@ module.exports = {"name":"strong-log-transformer","version":"2.1.0","description /***/ }), /* 131 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "workspacePackagePaths", function() { return workspacePackagePaths; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return copyWorkspacePackages; }); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(132); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(54); +/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(35); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.copyWorkspacePackages = exports.workspacePackagePaths = undefined; - -let workspacePackagePaths = exports.workspacePackagePaths = (() => { - var _ref = _asyncToGenerator(function* (rootPath) { - const rootPkgJson = yield (0, _package_json.readPackageJson)(_path2.default.join(rootPath, 'package.json')); - if (!rootPkgJson.workspaces) { - return []; - } - const workspacesPathsPatterns = rootPkgJson.workspaces.packages; - let workspaceProjectsPaths = []; - for (const pattern of workspacesPathsPatterns) { - workspaceProjectsPaths = workspaceProjectsPaths.concat((yield packagesFromGlobPattern({ pattern, rootPath }))); - } - // Filter out exclude glob patterns - for (const pattern of workspacesPathsPatterns) { - if (pattern.startsWith('!')) { - const pathToRemove = _path2.default.join(rootPath, pattern.slice(1), 'package.json'); - workspaceProjectsPaths = workspaceProjectsPaths.filter(function (p) { - return p !== pathToRemove; - }); - } - } - return workspaceProjectsPaths; - }); - return function workspacePackagePaths(_x) { - return _ref.apply(this, arguments); - }; -})(); -let copyWorkspacePackages = exports.copyWorkspacePackages = (() => { - var _ref2 = _asyncToGenerator(function* (rootPath) { - const workspaceProjects = yield getWorkspaceProjects(rootPath); - for (const project of workspaceProjects.values()) { - const dest = _path2.default.resolve(rootPath, 'node_modules', project.name); - // Remove the symlink - yield (0, _fs.unlink)(dest); - // Copy in the package - yield (0, _fs.copyDirectory)(project.path, dest); - } - }); - return function copyWorkspacePackages(_x2) { - return _ref2.apply(this, arguments); - }; -})(); - -let getWorkspaceProjects = (() => { - var _ref3 = _asyncToGenerator(function* (rootPath) { - const projectPaths = (0, _config.getProjectPaths)(rootPath, {}); - const projects = yield (0, _projects.getProjects)(rootPath, projectPaths); - for (const [key, project] of projects.entries()) { - if (!project.isWorkspaceProject) { - projects.delete(key); - } - } - return projects; - }); - return function getWorkspaceProjects(_x3) { - return _ref3.apply(this, arguments); - }; -})(); -var _glob = __webpack_require__(36); +const glob = Object(util__WEBPACK_IMPORTED_MODULE_2__["promisify"])(glob__WEBPACK_IMPORTED_MODULE_0___default.a); +async function workspacePackagePaths(rootPath) { + const rootPkgJson = await Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["readPackageJson"])(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(rootPath, 'package.json')); -var _glob2 = _interopRequireDefault(_glob); + if (!rootPkgJson.workspaces) { + return []; + } -var _path = __webpack_require__(16); + const workspacesPathsPatterns = rootPkgJson.workspaces.packages; + let workspaceProjectsPaths = []; -var _path2 = _interopRequireDefault(_path); + for (const pattern of workspacesPathsPatterns) { + workspaceProjectsPaths = workspaceProjectsPaths.concat((await packagesFromGlobPattern({ + pattern, + rootPath + }))); + } // Filter out exclude glob patterns -var _util = __webpack_require__(29); -var _config = __webpack_require__(132); + for (const pattern of workspacesPathsPatterns) { + if (pattern.startsWith('!')) { + const pathToRemove = path__WEBPACK_IMPORTED_MODULE_1___default.a.join(rootPath, pattern.slice(1), 'package.json'); + workspaceProjectsPaths = workspaceProjectsPaths.filter(p => p !== pathToRemove); + } + } -var _fs = __webpack_require__(20); + return workspaceProjectsPaths; +} +async function copyWorkspacePackages(rootPath) { + const workspaceProjects = await getWorkspaceProjects(rootPath); -var _package_json = __webpack_require__(54); + for (const project of workspaceProjects.values()) { + const dest = path__WEBPACK_IMPORTED_MODULE_1___default.a.resolve(rootPath, 'node_modules', project.name); // Remove the symlink -var _projects = __webpack_require__(35); + await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["unlink"])(dest); // Copy in the package -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["copyDirectory"])(project.path, dest); + } +} -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ +async function getWorkspaceProjects(rootPath) { + const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])(rootPath, {}); + const projects = await Object(_projects__WEBPACK_IMPORTED_MODULE_6__["getProjects"])(rootPath, projectPaths); + for (const [key, project] of projects.entries()) { + if (!project.isWorkspaceProject) { + projects.delete(key); + } + } -const glob = (0, _util.promisify)(_glob2.default); + return projects; +} -function packagesFromGlobPattern({ pattern, rootPath }) { - const globOptions = { - cwd: rootPath, - // Should throw in case of unusual errors when reading the file system - strict: true, - // Always returns absolute paths for matched files - absolute: true, - // Do not match ** against multiple filenames - // (This is only specified because we currently don't have a need for it.) - noglobstar: true - }; - return glob(_path2.default.join(pattern, 'package.json'), globOptions); +function packagesFromGlobPattern({ + pattern, + rootPath +}) { + const globOptions = { + cwd: rootPath, + // Should throw in case of unusual errors when reading the file system + strict: true, + // Always returns absolute paths for matched files + absolute: true, + // Do not match ** against multiple filenames + // (This is only specified because we currently don't have a need for it.) + noglobstar: true + }; + return glob(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(pattern, 'package.json'), globOptions); } /***/ }), /* 132 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return getProjectPaths; }); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getProjectPaths = getProjectPaths; - -var _path = __webpack_require__(16); - /** * Returns all the paths where plugins are located */ function getProjectPaths(rootPath, options) { - const skipKibanaPlugins = Boolean(options['skip-kibana-plugins']); - const ossOnly = Boolean(options.oss); - const projectPaths = [rootPath, (0, _path.resolve)(rootPath, 'packages/*')]; - // This is needed in order to install the dependencies for the declared - // plugin functional used in the selenium functional tests. - // As we are now using the webpack dll for the client vendors dependencies - // when we run the plugin functional tests against the distributable - // dependencies used by such plugins like @eui, react and react-dom can't - // be loaded from the dll as the context is different from the one declared - // into the webpack dll reference plugin. - // In anyway, have a plugin declaring their own dependencies is the - // correct and the expect behavior. - projectPaths.push((0, _path.resolve)(rootPath, 'test/plugin_functional/plugins/*')); - projectPaths.push((0, _path.resolve)(rootPath, 'test/interpreter_functional/plugins/*')); - if (!ossOnly) { - projectPaths.push((0, _path.resolve)(rootPath, 'x-pack')); - projectPaths.push((0, _path.resolve)(rootPath, 'x-pack/plugins/*')); - } - if (!skipKibanaPlugins) { - projectPaths.push((0, _path.resolve)(rootPath, '../kibana-extra/*')); - projectPaths.push((0, _path.resolve)(rootPath, '../kibana-extra/*/packages/*')); - projectPaths.push((0, _path.resolve)(rootPath, '../kibana-extra/*/plugins/*')); - projectPaths.push((0, _path.resolve)(rootPath, 'plugins/*')); - projectPaths.push((0, _path.resolve)(rootPath, 'plugins/*/packages/*')); - projectPaths.push((0, _path.resolve)(rootPath, 'plugins/*/plugins/*')); - } - return projectPaths; -} /* - * 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. - */ + const skipKibanaPlugins = Boolean(options['skip-kibana-plugins']); + const ossOnly = Boolean(options.oss); + const projectPaths = [rootPath, Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'packages/*')]; // This is needed in order to install the dependencies for the declared + // plugin functional used in the selenium functional tests. + // As we are now using the webpack dll for the client vendors dependencies + // when we run the plugin functional tests against the distributable + // dependencies used by such plugins like @eui, react and react-dom can't + // be loaded from the dll as the context is different from the one declared + // into the webpack dll reference plugin. + // In anyway, have a plugin declaring their own dependencies is the + // correct and the expect behavior. -/***/ }), -/* 133 */ -/***/ (function(module, exports, __webpack_require__) { + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/plugin_functional/plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/interpreter_functional/plugins/*')); -"use strict"; + if (!ossOnly) { + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/plugins/*')); + } + if (!skipKibanaPlugins) { + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*/packages/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*/plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*/packages/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*/plugins/*')); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.CleanCommand = undefined; + return projectPaths; +} -var _chalk = __webpack_require__(2); +/***/ }), +/* 133 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { -var _chalk2 = _interopRequireDefault(_chalk); +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(134); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(148); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); +/* + * 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. + */ -var _del = __webpack_require__(134); -var _del2 = _interopRequireDefault(_del); -var _ora = __webpack_require__(148); -var _ora2 = _interopRequireDefault(_ora); -var _path = __webpack_require__(16); -var _fs = __webpack_require__(20); +const CleanCommand = { + description: 'Remove the node_modules and target directories from all projects.', + name: 'clean', -var _log = __webpack_require__(33); + async run(projects) { + const toDelete = []; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + for (const project of projects.values()) { + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(project.nodeModulesLocation)) { + toDelete.push({ + cwd: project.path, + pattern: Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(project.path, project.nodeModulesLocation) + }); + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(project.targetLocation)) { + toDelete.push({ + cwd: project.path, + pattern: Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(project.path, project.targetLocation) + }); + } + const { + extraPatterns + } = project.getCleanConfig(); -const CleanCommand = exports.CleanCommand = { - description: 'Remove the node_modules and target directories from all projects.', - name: 'clean', - run(projects) { - return _asyncToGenerator(function* () { - const toDelete = []; - for (const project of projects.values()) { - if (yield (0, _fs.isDirectory)(project.nodeModulesLocation)) { - toDelete.push({ - cwd: project.path, - pattern: (0, _path.relative)(project.path, project.nodeModulesLocation) - }); - } - if (yield (0, _fs.isDirectory)(project.targetLocation)) { - toDelete.push({ - cwd: project.path, - pattern: (0, _path.relative)(project.path, project.targetLocation) - }); - } - const { extraPatterns } = project.getCleanConfig(); - if (extraPatterns) { - toDelete.push({ - cwd: project.path, - pattern: extraPatterns - }); - } - } - if (toDelete.length === 0) { - _log.log.write(_chalk2.default.bold.green('\n\nNothing to delete')); - } else { - _log.log.write(_chalk2.default.bold.red('\n\nDeleting:\n')); - /** - * In order to avoid patterns like `/build` in packages from accidentally - * impacting files outside the package we use `process.chdir()` to change - * the cwd to the package and execute `del()` without the `force` option - * so it will check that each file being deleted is within the package. - * - * `del()` does support a `cwd` option, but it's only for resolving the - * patterns and does not impact the cwd check. - */ - const originalCwd = process.cwd(); - try { - for (const _ref of toDelete) { - const { pattern, cwd } = _ref; + if (extraPatterns) { + toDelete.push({ + cwd: project.path, + pattern: extraPatterns + }); + } + } - process.chdir(cwd); - const promise = (0, _del2.default)(pattern); - _ora2.default.promise(promise, (0, _path.relative)(originalCwd, (0, _path.join)(cwd, String(pattern)))); - yield promise; - } - } finally { - process.chdir(originalCwd); - } - } - })(); + if (toDelete.length === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.green('\n\nNothing to delete')); + } else { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.red('\n\nDeleting:\n')); + /** + * In order to avoid patterns like `/build` in packages from accidentally + * impacting files outside the package we use `process.chdir()` to change + * the cwd to the package and execute `del()` without the `force` option + * so it will check that each file being deleted is within the package. + * + * `del()` does support a `cwd` option, but it's only for resolving the + * patterns and does not impact the cwd check. + */ + + const originalCwd = process.cwd(); + + try { + for (const _ref of toDelete) { + const { + pattern, + cwd + } = _ref; + process.chdir(cwd); + const promise = del__WEBPACK_IMPORTED_MODULE_1___default()(pattern); + ora__WEBPACK_IMPORTED_MODULE_2___default.a.promise(promise, Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(originalCwd, Object(path__WEBPACK_IMPORTED_MODULE_3__["join"])(cwd, String(pattern)))); + await promise; + } + } finally { + process.chdir(originalCwd); + } } + } + }; /***/ }), @@ -19288,120 +19196,99 @@ module.exports = {"dots":{"interval":80,"frames":["⠋","⠙","⠹","⠸","⠼", /***/ }), /* 155 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RunCommand", function() { return RunCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(33); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(35); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.RunCommand = undefined; - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _log = __webpack_require__(33); - -var _parallelize = __webpack_require__(34); - -var _projects = __webpack_require__(35); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ - - -const RunCommand = exports.RunCommand = { - description: 'Run script defined in package.json in each package that contains that script.', - name: 'run', - run(projects, projectGraph, { extraArgs }) { - return _asyncToGenerator(function* () { - const batchedProjects = (0, _projects.topologicallyBatchProjects)(projects, projectGraph); - if (extraArgs.length === 0) { - _log.log.write(_chalk2.default.red.bold('\nNo script specified')); - process.exit(1); - } - const scriptName = extraArgs[0]; - const scriptArgs = extraArgs.slice(1); - _log.log.write(_chalk2.default.bold(`\nRunning script [${_chalk2.default.green(scriptName)}] in batched topological order\n`)); - yield (0, _parallelize.parallelizeBatches)(batchedProjects, (() => { - var _ref = _asyncToGenerator(function* (pkg) { - if (pkg.hasScript(scriptName)) { - yield pkg.runScriptStreaming(scriptName, scriptArgs); - } - }); - - return function (_x) { - return _ref.apply(this, arguments); - }; - })()); - })(); - } -}; -/***/ }), -/* 156 */ -/***/ (function(module, exports, __webpack_require__) { -"use strict"; +const RunCommand = { + description: 'Run script defined in package.json in each package that contains that script.', + name: 'run', + async run(projects, projectGraph, { + extraArgs + }) { + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projects, projectGraph); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WatchCommand = undefined; + if (extraArgs.length === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red.bold('\nNo script specified')); + process.exit(1); + } -var _chalk = __webpack_require__(2); + const scriptName = extraArgs[0]; + const scriptArgs = extraArgs.slice(1); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`\nRunning script [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(scriptName)}] in batched topological order\n`)); + await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async pkg => { + if (pkg.hasScript(scriptName)) { + await pkg.runScriptStreaming(scriptName, scriptArgs); + } + }); + } -var _chalk2 = _interopRequireDefault(_chalk); +}; -var _log = __webpack_require__(33); +/***/ }), +/* 156 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { -var _parallelize = __webpack_require__(34); +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WatchCommand", function() { return WatchCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(33); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(35); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(157); +/* + * 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. + */ -var _projects = __webpack_require__(35); -var _watch = __webpack_require__(157); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ /** @@ -19411,6 +19298,7 @@ const watchScriptName = 'kbn:watch'; /** * Name of the Kibana project. */ + const kibanaProjectName = 'kibana'; /** * Command that traverses through list of available projects/packages that have `kbn:watch` script in their @@ -19422,68 +19310,54 @@ const kibanaProjectName = 'kibana'; * the `kbn:watch` script and eventually for the entire batch. Currently we support completion "markers" for * `webpack` and `tsc` only, for the rest we rely on predefined timeouts. */ -const WatchCommand = exports.WatchCommand = { - description: 'Runs `kbn:watch` script for every project.', - name: 'watch', - run(projects, projectGraph) { - return _asyncToGenerator(function* () { - const projectsToWatch = new Map(); - for (const project of projects.values()) { - // We can't watch project that doesn't have `kbn:watch` script. - if (project.hasScript(watchScriptName)) { - projectsToWatch.set(project.name, project); - } - } - if (projectsToWatch.size === 0) { - _log.log.write(_chalk2.default.red(`\nThere are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.\n`)); - return; - } - const projectNames = Array.from(projectsToWatch.keys()); - _log.log.write(_chalk2.default.bold(_chalk2.default.green(`Running ${watchScriptName} scripts for [${projectNames.join(', ')}].`))); - // Kibana should always be run the last, so we don't rely on automatic - // topological batching and push it to the last one-entry batch manually. - const shouldWatchKibanaProject = projectsToWatch.delete(kibanaProjectName); - const batchedProjects = (0, _projects.topologicallyBatchProjects)(projectsToWatch, projectGraph); - if (shouldWatchKibanaProject) { - batchedProjects.push([projects.get(kibanaProjectName)]); - } - yield (0, _parallelize.parallelizeBatches)(batchedProjects, (() => { - var _ref = _asyncToGenerator(function* (pkg) { - const completionHint = yield (0, _watch.waitUntilWatchIsReady)(pkg.runScriptStreaming(watchScriptName).stdout); - _log.log.write(_chalk2.default.bold(`[${_chalk2.default.green(pkg.name)}] Initial build completed (${completionHint}).`)); - }); - return function (_x) { - return _ref.apply(this, arguments); - }; - })()); - })(); - } -}; +const WatchCommand = { + description: 'Runs `kbn:watch` script for every project.', + name: 'watch', -/***/ }), -/* 157 */ -/***/ (function(module, exports, __webpack_require__) { + async run(projects, projectGraph) { + const projectsToWatch = new Map(); -"use strict"; + for (const project of projects.values()) { + // We can't watch project that doesn't have `kbn:watch` script. + if (project.hasScript(watchScriptName)) { + projectsToWatch.set(project.name, project); + } + } + if (projectsToWatch.size === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`\nThere are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.\n`)); + return; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.waitUntilWatchIsReady = waitUntilWatchIsReady; + const projectNames = Array.from(projectsToWatch.keys()); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(`Running ${watchScriptName} scripts for [${projectNames.join(', ')}].`))); // Kibana should always be run the last, so we don't rely on automatic + // topological batching and push it to the last one-entry batch manually. -var _rxjs = __webpack_require__(158); + const shouldWatchKibanaProject = projectsToWatch.delete(kibanaProjectName); + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projectsToWatch, projectGraph); -var Rx = _interopRequireWildcard(_rxjs); + if (shouldWatchKibanaProject) { + batchedProjects.push([projects.get(kibanaProjectName)]); + } -var _operators = __webpack_require__(257); + await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async pkg => { + const completionHint = await Object(_utils_watch__WEBPACK_IMPORTED_MODULE_4__["waitUntilWatchIsReady"])(pkg.runScriptStreaming(watchScriptName).stdout); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`[${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(pkg.name)}] Initial build completed (${completionHint}).`)); + }); + } -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } +}; -/** - * Number of milliseconds we wait before we fall back to the default watch handler. - */ +/***/ }), +/* 157 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "waitUntilWatchIsReady", function() { return waitUntilWatchIsReady; }); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(158); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -19502,27 +19376,46 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; * specific language governing permissions and limitations * under the License. */ + + +/** + * Number of milliseconds we wait before we fall back to the default watch handler. + */ + const defaultHandlerDelay = 3000; /** * If default watch handler is used, then it's the number of milliseconds we wait for * any build output before we consider watch task ready. */ + const defaultHandlerReadinessTimeout = 2000; -function getWatchHandlers(buildOutput$, { handlerDelay = defaultHandlerDelay, handlerReadinessTimeout = defaultHandlerReadinessTimeout }) { - const typescriptHandler = buildOutput$.pipe((0, _operators.first)(data => data.includes('$ tsc')), (0, _operators.map)(() => buildOutput$.pipe((0, _operators.first)(data => data.includes('Compilation complete.')), (0, _operators.mapTo)('tsc')))); - const webpackHandler = buildOutput$.pipe((0, _operators.first)(data => data.includes('$ webpack')), (0, _operators.map)(() => buildOutput$.pipe((0, _operators.first)(data => data.includes('Chunk Names')), (0, _operators.mapTo)('webpack')))); - const defaultHandler = Rx.of(undefined).pipe((0, _operators.delay)(handlerReadinessTimeout), (0, _operators.map)(() => buildOutput$.pipe((0, _operators.timeout)(handlerDelay), (0, _operators.catchError)(() => Rx.of('timeout'))))); +/** + * Describes configurable watch options. + */ + +function getWatchHandlers(buildOutput$, { + handlerDelay = defaultHandlerDelay, + handlerReadinessTimeout = defaultHandlerReadinessTimeout +}) { + const typescriptHandler = buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["first"])(data => data.includes('$ tsc')), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["map"])(() => buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["first"])(data => data.includes('Compilation complete.')), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["mapTo"])('tsc')))); + const webpackHandler = buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["first"])(data => data.includes('$ webpack')), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["map"])(() => buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["first"])(data => data.includes('Chunk Names')), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["mapTo"])('webpack')))); + const defaultHandler = rxjs__WEBPACK_IMPORTED_MODULE_0__["of"](undefined).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["delay"])(handlerReadinessTimeout), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["map"])(() => buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["timeout"])(handlerDelay), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["catchError"])(() => rxjs__WEBPACK_IMPORTED_MODULE_0__["of"]('timeout'))))); return [typescriptHandler, webpackHandler, defaultHandler]; } + function waitUntilWatchIsReady(stream, opts = {}) { - const buildOutput$ = new Rx.Subject(); + const buildOutput$ = new rxjs__WEBPACK_IMPORTED_MODULE_0__["Subject"](); + const onDataListener = data => buildOutput$.next(data.toString('utf-8')); + const onEndListener = () => buildOutput$.complete(); + const onErrorListener = e => buildOutput$.error(e); + stream.once('end', onEndListener); stream.once('error', onErrorListener); stream.on('data', onDataListener); - return Rx.race(getWatchHandlers(buildOutput$, opts)).pipe((0, _operators.mergeMap)(whenReady => whenReady), (0, _operators.finalize)(() => { + return rxjs__WEBPACK_IMPORTED_MODULE_0__["race"](getWatchHandlers(buildOutput$, opts)).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["mergeMap"])(whenReady => whenReady), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["finalize"])(() => { stream.removeListener('data', onDataListener); stream.removeListener('end', onEndListener); stream.removeListener('error', onErrorListener); @@ -31110,108 +31003,96 @@ function zipAll(project) { /***/ }), /* 357 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(358); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(359); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(132); +/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(52); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(35); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(366); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.runCommand = undefined; - -let runCommand = exports.runCommand = (() => { - var _ref = _asyncToGenerator(function* (command, config) { - try { - _log.log.write(_chalk2.default.bold(`Running [${_chalk2.default.green(command.name)}] command from [${_chalk2.default.yellow(config.rootPath)}]:\n`)); - const projectPaths = (0, _config.getProjectPaths)(config.rootPath, config.options); - const projects = yield (0, _projects.getProjects)(config.rootPath, projectPaths, { - exclude: toArray(config.options.exclude), - include: toArray(config.options.include) - }); - if (projects.size === 0) { - _log.log.write(_chalk2.default.red(`There are no projects found. Double check project name(s) in '-i/--include' and '-e/--exclude' filters.\n`)); - return process.exit(1); - } - const projectGraph = (0, _projects.buildProjectGraph)(projects); - _log.log.write(_chalk2.default.bold(`Found [${_chalk2.default.green(projects.size.toString())}] projects:\n`)); - _log.log.write((0, _projects_tree.renderProjectsTree)(config.rootPath, projects)); - yield command.run(projects, projectGraph, config); - } catch (e) { - _log.log.write(_chalk2.default.bold.red(`\n[${command.name}] failed:\n`)); - if (e instanceof _errors.CliError) { - const msg = _chalk2.default.red(`CliError: ${e.message}\n`); - _log.log.write((0, _wrapAnsi2.default)(msg, 80)); - const keys = Object.keys(e.meta); - if (keys.length > 0) { - const metaOutput = keys.map(function (key) { - const value = e.meta[key]; - return `${key}: ${value}`; - }); - _log.log.write('Additional debugging info:\n'); - _log.log.write((0, _indentString2.default)(metaOutput.join('\n'), 3)); - } - } else { - _log.log.write(e.stack); - } - process.exit(1); - } - }); - - return function runCommand(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _indentString = __webpack_require__(358); -var _indentString2 = _interopRequireDefault(_indentString); -var _wrapAnsi = __webpack_require__(359); -var _wrapAnsi2 = _interopRequireDefault(_wrapAnsi); -var _config = __webpack_require__(132); -var _errors = __webpack_require__(52); -var _log = __webpack_require__(33); +async function runCommand(command, config) { + try { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`Running [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(command.name)}] command from [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.yellow(config.rootPath)}]:\n`)); + const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])(config.rootPath, config.options); + const projects = await Object(_utils_projects__WEBPACK_IMPORTED_MODULE_6__["getProjects"])(config.rootPath, projectPaths, { + exclude: toArray(config.options.exclude), + include: toArray(config.options.include) + }); -var _projects = __webpack_require__(35); + if (projects.size === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`There are no projects found. Double check project name(s) in '-i/--include' and '-e/--exclude' filters.\n`)); + return process.exit(1); + } -var _projects_tree = __webpack_require__(366); + const projectGraph = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_6__["buildProjectGraph"])(projects); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`Found [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(projects.size.toString())}] projects:\n`)); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(Object(_utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__["renderProjectsTree"])(config.rootPath, projects)); + await command.run(projects, projectGraph, config); + } catch (e) { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.red(`\n[${command.name}] failed:\n`)); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + if (e instanceof _utils_errors__WEBPACK_IMPORTED_MODULE_4__["CliError"]) { + const msg = chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`CliError: ${e.message}\n`); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default()(msg, 80)); + const keys = Object.keys(e.meta); -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + if (keys.length > 0) { + const metaOutput = keys.map(key => { + const value = e.meta[key]; + return `${key}: ${value}`; + }); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write('Additional debugging info:\n'); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(indent_string__WEBPACK_IMPORTED_MODULE_1___default()(metaOutput.join('\n'), 3)); + } + } else { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(e.stack); + } + process.exit(1); + } +} function toArray(value) { - if (value == null) { - return []; - } - return Array.isArray(value) ? value : [value]; + if (value == null) { + return []; + } + + return Array.isArray(value) ? value : [value]; } /***/ }), @@ -31602,26 +31483,15 @@ module.exports = () => { /***/ }), /* 366 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.renderProjectsTree = renderProjectsTree; - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _path = __webpack_require__(16); - -var _path2 = _interopRequireDefault(_path); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renderProjectsTree", function() { return renderProjectsTree; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -31640,173 +31510,228 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de * specific language governing permissions and limitations * under the License. */ + + const projectKey = Symbol('__project'); function renderProjectsTree(rootPath, projects) { - const projectsTree = buildProjectsTree(rootPath, projects); - return treeToString(createTreeStructure(projectsTree)); + const projectsTree = buildProjectsTree(rootPath, projects); + return treeToString(createTreeStructure(projectsTree)); } + function treeToString(tree) { - return [tree.name].concat(childrenToStrings(tree.children, '')).join('\n'); + return [tree.name].concat(childrenToStrings(tree.children, '')).join('\n'); } + function childrenToStrings(tree, treePrefix) { - if (tree === undefined) { - return []; - } - let strings = []; - tree.forEach((node, index) => { - const isLastNode = tree.length - 1 === index; - const nodePrefix = isLastNode ? '└── ' : '├── '; - const childPrefix = isLastNode ? ' ' : '│ '; - const childrenPrefix = treePrefix + childPrefix; - strings.push(`${treePrefix}${nodePrefix}${node.name}`); - strings = strings.concat(childrenToStrings(node.children, childrenPrefix)); - }); - return strings; + if (tree === undefined) { + return []; + } + + let strings = []; + tree.forEach((node, index) => { + const isLastNode = tree.length - 1 === index; + const nodePrefix = isLastNode ? '└── ' : '├── '; + const childPrefix = isLastNode ? ' ' : '│ '; + const childrenPrefix = treePrefix + childPrefix; + strings.push(`${treePrefix}${nodePrefix}${node.name}`); + strings = strings.concat(childrenToStrings(node.children, childrenPrefix)); + }); + return strings; } + function createTreeStructure(tree) { - let name; - const children = []; - for (const [dir, project] of tree.entries()) { - // This is a leaf node (aka a project) - if (typeof project === 'string') { - name = _chalk2.default.green(project); - continue; - } - // If there's only one project and the key indicates it's a leaf node, we - // know that we're at a package folder that contains a package.json, so we - // "inline it" so we don't get unnecessary levels, i.e. we'll just see - // `foo` instead of `foo -> foo`. - if (project.size === 1 && project.has(projectKey)) { - const projectName = project.get(projectKey); - children.push({ - children: [], - name: dirOrProjectName(dir, projectName) - }); - continue; - } - const subtree = createTreeStructure(project); - // If the name is specified, we know there's a package at the "root" of the - // subtree itself. - if (subtree.name !== undefined) { - const projectName = subtree.name; - children.push({ - children: subtree.children, - name: dirOrProjectName(dir, projectName) - }); - continue; - } - // Special-case whenever we have one child, so we don't get unnecessary - // folders in the output. E.g. instead of `foo -> bar -> baz` we get - // `foo/bar/baz` instead. - if (subtree.children && subtree.children.length === 1) { - const child = subtree.children[0]; - const newName = _chalk2.default.dim(_path2.default.join(dir.toString(), child.name)); - children.push({ - children: child.children, - name: newName - }); - continue; - } - children.push({ - children: subtree.children, - name: _chalk2.default.dim(dir.toString()) - }); + let name; + const children = []; + + for (const [dir, project] of tree.entries()) { + // This is a leaf node (aka a project) + if (typeof project === 'string') { + name = chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(project); + continue; + } // If there's only one project and the key indicates it's a leaf node, we + // know that we're at a package folder that contains a package.json, so we + // "inline it" so we don't get unnecessary levels, i.e. we'll just see + // `foo` instead of `foo -> foo`. + + + if (project.size === 1 && project.has(projectKey)) { + const projectName = project.get(projectKey); + children.push({ + children: [], + name: dirOrProjectName(dir, projectName) + }); + continue; } - return { name, children }; + + const subtree = createTreeStructure(project); // If the name is specified, we know there's a package at the "root" of the + // subtree itself. + + if (subtree.name !== undefined) { + const projectName = subtree.name; + children.push({ + children: subtree.children, + name: dirOrProjectName(dir, projectName) + }); + continue; + } // Special-case whenever we have one child, so we don't get unnecessary + // folders in the output. E.g. instead of `foo -> bar -> baz` we get + // `foo/bar/baz` instead. + + + if (subtree.children && subtree.children.length === 1) { + const child = subtree.children[0]; + const newName = chalk__WEBPACK_IMPORTED_MODULE_0___default.a.dim(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(dir.toString(), child.name)); + children.push({ + children: child.children, + name: newName + }); + continue; + } + + children.push({ + children: subtree.children, + name: chalk__WEBPACK_IMPORTED_MODULE_0___default.a.dim(dir.toString()) + }); + } + + return { + name, + children + }; } + function dirOrProjectName(dir, projectName) { - return dir === projectName ? _chalk2.default.green(dir) : _chalk2.default`{dim ${dir.toString()} ({reset.green ${projectName}})}`; + return dir === projectName ? chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(dir) : chalk__WEBPACK_IMPORTED_MODULE_0___default.a`{dim ${dir.toString()} ({reset.green ${projectName}})}`; } + function buildProjectsTree(rootPath, projects) { - const tree = new Map(); - for (const project of projects.values()) { - if (rootPath === project.path) { - tree.set(projectKey, project.name); - } else { - const relativeProjectPath = _path2.default.relative(rootPath, project.path); - addProjectToTree(tree, relativeProjectPath.split(_path2.default.sep), project); - } + const tree = new Map(); + + for (const project of projects.values()) { + if (rootPath === project.path) { + tree.set(projectKey, project.name); + } else { + const relativeProjectPath = path__WEBPACK_IMPORTED_MODULE_1___default.a.relative(rootPath, project.path); + addProjectToTree(tree, relativeProjectPath.split(path__WEBPACK_IMPORTED_MODULE_1___default.a.sep), project); } - return tree; + } + + return tree; } + function addProjectToTree(tree, pathParts, project) { - if (pathParts.length === 0) { - tree.set(projectKey, project.name); - } else { - const [currentDir, ...rest] = pathParts; - if (!tree.has(currentDir)) { - tree.set(currentDir, new Map()); - } - const subtree = tree.get(currentDir); - addProjectToTree(subtree, rest, project); + if (pathParts.length === 0) { + tree.set(projectKey, project.name); + } else { + const [currentDir, ...rest] = pathParts; + + if (!tree.has(currentDir)) { + tree.set(currentDir, new Map()); } + + const subtree = tree.get(currentDir); + addProjectToTree(subtree, rest, project); + } } /***/ }), /* 367 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(368); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(547); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _build_production_projects = __webpack_require__(368); - -Object.defineProperty(exports, 'buildProductionProjects', { - enumerable: true, - get: function () { - return _build_production_projects.buildProductionProjects; - } -}); +/* + * 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. + */ -var _prepare_project_dependencies = __webpack_require__(547); -Object.defineProperty(exports, 'prepareExternalProjectDependencies', { - enumerable: true, - get: function () { - return _prepare_project_dependencies.prepareExternalProjectDependencies; - } -}); /***/ }), /* 368 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(369); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(134); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(132); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(54); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(35); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.buildProductionProjects = undefined; - -let buildProductionProjects = exports.buildProductionProjects = (() => { - var _ref = _asyncToGenerator(function* ({ kibanaRoot, buildRoots }) { - const projects = yield getProductionProjects(kibanaRoot); - const projectGraph = (0, _projects.buildProjectGraph)(projects); - const batchedProjects = (0, _projects.topologicallyBatchProjects)(projects, projectGraph); - const projectNames = [...projects.values()].map(function (project) { - return project.name; - }); - _log.log.write(`Preparing production build for [${projectNames.join(', ')}]`); - for (const batch of batchedProjects) { - for (const project of batch) { - yield deleteTarget(project); - yield buildProject(project); - for (const buildRoot of buildRoots) { - yield copyToBuild(project, kibanaRoot, buildRoot); - } - } - } - }); - return function buildProductionProjects(_x) { - return _ref.apply(this, arguments); - }; -})(); + + + + + +async function buildProductionProjects({ + kibanaRoot, + buildRoots +}) { + const projects = await getProductionProjects(kibanaRoot); + const projectGraph = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["buildProjectGraph"])(projects); + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["topologicallyBatchProjects"])(projects, projectGraph); + const projectNames = [...projects.values()].map(project => project.name); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(`Preparing production build for [${projectNames.join(', ')}]`); + + for (const batch of batchedProjects) { + for (const project of batch) { + await deleteTarget(project); + await buildProject(project); + + for (const buildRoot of buildRoots) { + await copyToBuild(project, kibanaRoot, buildRoot); + } + } + } +} /** * Returns the subset of projects that should be built into the production * bundle. As we copy these into Kibana's `node_modules` during the build step, @@ -31814,48 +31739,32 @@ let buildProductionProjects = exports.buildProductionProjects = (() => { * we only include Kibana's transitive _production_ dependencies. */ +async function getProductionProjects(rootPath) { + const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])(rootPath, {}); + const projects = await Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["getProjects"])(rootPath, projectPaths); + const productionProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["includeTransitiveProjects"])([projects.get('kibana')], projects, { + onlyProductionDependencies: true + }); // We remove Kibana, as we're already building Kibana -let getProductionProjects = (() => { - var _ref2 = _asyncToGenerator(function* (rootPath) { - const projectPaths = (0, _config.getProjectPaths)(rootPath, {}); - const projects = yield (0, _projects.getProjects)(rootPath, projectPaths); - const productionProjects = (0, _projects.includeTransitiveProjects)([projects.get('kibana')], projects, { - onlyProductionDependencies: true - }); - // We remove Kibana, as we're already building Kibana - productionProjects.delete('kibana'); - return productionProjects; - }); - - return function getProductionProjects(_x2) { - return _ref2.apply(this, arguments); - }; -})(); - -let deleteTarget = (() => { - var _ref3 = _asyncToGenerator(function* (project) { - const targetDir = project.targetLocation; - if (yield (0, _fs.isDirectory)(targetDir)) { - yield (0, _del2.default)(targetDir, { force: true }); - } - }); + productionProjects.delete('kibana'); + return productionProjects; +} - return function deleteTarget(_x3) { - return _ref3.apply(this, arguments); - }; -})(); +async function deleteTarget(project) { + const targetDir = project.targetLocation; -let buildProject = (() => { - var _ref4 = _asyncToGenerator(function* (project) { - if (project.hasScript('build')) { - yield project.runScript('build'); - } + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(targetDir)) { + await del__WEBPACK_IMPORTED_MODULE_1___default()(targetDir, { + force: true }); + } +} - return function buildProject(_x4) { - return _ref4.apply(this, arguments); - }; -})(); +async function buildProject(project) { + if (project.hasScript('build')) { + await project.runScript('build'); + } +} /** * Copy all the project's files from its "intermediate build directory" and * into the build. The intermediate directory can either be the root of the @@ -31869,73 +31778,26 @@ let buildProject = (() => { */ -let copyToBuild = (() => { - var _ref5 = _asyncToGenerator(function* (project, kibanaRoot, buildRoot) { - // We want the package to have the same relative location within the build - const relativeProjectPath = (0, _path.relative)(kibanaRoot, project.path); - const buildProjectPath = (0, _path.resolve)(buildRoot, relativeProjectPath); - yield (0, _cpy2.default)(['**/*', '!node_modules/**'], buildProjectPath, { - cwd: project.getIntermediateBuildDirectory(), - dot: true, - nodir: true, - parents: true - }); - // If a project is using an intermediate build directory, we special-case our - // handling of `package.json`, as the project build process might have copied - // (a potentially modified) `package.json` into the intermediate build - // directory already. If so, we want to use that `package.json` as the basis - // for creating the production-ready `package.json`. If it's not present in - // the intermediate build, we fall back to using the project's already defined - // `package.json`. - const packageJson = (yield (0, _fs.isFile)((0, _path.join)(buildProjectPath, 'package.json'))) ? yield (0, _package_json.readPackageJson)(buildProjectPath) : project.json; - yield (0, _package_json.writePackageJson)(buildProjectPath, packageJson); - }); - - return function copyToBuild(_x5, _x6, _x7) { - return _ref5.apply(this, arguments); - }; -})(); - -var _cpy = __webpack_require__(369); - -var _cpy2 = _interopRequireDefault(_cpy); - -var _del = __webpack_require__(134); - -var _del2 = _interopRequireDefault(_del); - -var _path = __webpack_require__(16); - -var _config = __webpack_require__(132); - -var _fs = __webpack_require__(20); +async function copyToBuild(project, kibanaRoot, buildRoot) { + // We want the package to have the same relative location within the build + const relativeProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(kibanaRoot, project.path); + const buildProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["resolve"])(buildRoot, relativeProjectPath); + await cpy__WEBPACK_IMPORTED_MODULE_0___default()(['**/*', '!node_modules/**'], buildProjectPath, { + cwd: project.getIntermediateBuildDirectory(), + dot: true, + nodir: true, + parents: true + }); // If a project is using an intermediate build directory, we special-case our + // handling of `package.json`, as the project build process might have copied + // (a potentially modified) `package.json` into the intermediate build + // directory already. If so, we want to use that `package.json` as the basis + // for creating the production-ready `package.json`. If it's not present in + // the intermediate build, we fall back to using the project's already defined + // `package.json`. -var _log = __webpack_require__(33); - -var _package_json = __webpack_require__(54); - -var _projects = __webpack_require__(35); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + const packageJson = (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isFile"])(Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(buildProjectPath, 'package.json'))) ? await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["readPackageJson"])(buildProjectPath) : project.json; + await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["writePackageJson"])(buildProjectPath, packageJson); +} /***/ }), /* 369 */ @@ -55219,75 +55081,67 @@ module.exports = CpyError; /***/ }), /* 547 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return prepareExternalProjectDependencies; }); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54); +/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(53); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.prepareExternalProjectDependencies = undefined; +/** + * All external projects are located within `./plugins/{plugin}` relative + * to the Kibana root directory or `../kibana-extra/{plugin}` relative + * to Kibana itself. + */ +const isKibanaDep = depVersion => depVersion.includes('../../kibana/'); /** * This prepares the dependencies for an _external_ project. */ -let prepareExternalProjectDependencies = exports.prepareExternalProjectDependencies = (() => { - var _ref = _asyncToGenerator(function* (projectPath) { - const project = yield _project.Project.fromPath(projectPath); - if (!project.hasDependencies()) { - return; - } - const deps = project.allDependencies; - for (const depName of Object.keys(deps)) { - const depVersion = deps[depName]; - // Kibana currently only supports `link:` dependencies on Kibana's own - // packages, as these are packaged into the `node_modules` folder when - // Kibana is built, so we don't need to take any action to enable - // `require(...)` to resolve for these packages. - if ((0, _package_json.isLinkDependency)(depVersion) && !isKibanaDep(depVersion)) { - // For non-Kibana packages we need to set up symlinks during the - // installation process, but this is not something we support yet. - throw new Error('This plugin is using `link:` dependencies for non-Kibana packages'); - } - } - }); - return function prepareExternalProjectDependencies(_x) { - return _ref.apply(this, arguments); - }; -})(); -var _package_json = __webpack_require__(54); +async function prepareExternalProjectDependencies(projectPath) { + const project = await _utils_project__WEBPACK_IMPORTED_MODULE_1__["Project"].fromPath(projectPath); -var _project = __webpack_require__(53); + if (!project.hasDependencies()) { + return; + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + const deps = project.allDependencies; + for (const depName of Object.keys(deps)) { + const depVersion = deps[depName]; // Kibana currently only supports `link:` dependencies on Kibana's own + // packages, as these are packaged into the `node_modules` folder when + // Kibana is built, so we don't need to take any action to enable + // `require(...)` to resolve for these packages. -/** - * All external projects are located within `./plugins/{plugin}` relative - * to the Kibana root directory or `../kibana-extra/{plugin}` relative - * to Kibana itself. - */ -const isKibanaDep = depVersion => depVersion.includes('../../kibana/'); + if (Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_0__["isLinkDependency"])(depVersion) && !isKibanaDep(depVersion)) { + // For non-Kibana packages we need to set up symlinks during the + // installation process, but this is not something we support yet. + throw new Error('This plugin is using `link:` dependencies for non-Kibana packages'); + } + } +} /***/ }) /******/ ]); \ No newline at end of file diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index 6248e919976db..86d67c0bcfe1f 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -10,6 +10,11 @@ "prettier": "prettier --write './src/**/*.ts'" }, "devDependencies": { + "@babel/core": "^7.3.4", + "@babel/plugin-proposal-class-properties": "^7.3.4", + "@babel/plugin-proposal-object-rest-spread": "^7.3.4", + "@babel/preset-env": "^7.3.4", + "@babel/preset-typescript": "^7.3.3", "@types/cmd-shim": "^2.0.0", "@types/cpy": "^5.1.0", "@types/dedent": "^0.7.0", @@ -32,10 +37,7 @@ "@types/tempy": "^0.1.0", "@types/wrap-ansi": "^2.0.14", "@types/write-pkg": "^3.1.0", - "babel-core": "^6.26.3", - "babel-loader": "^7.1.5", - "babel-preset-env": "^1.7.0", - "babel-preset-stage-3": "^6.24.1", + "babel-loader": "^8.0.5", "chalk": "^2.4.1", "cmd-shim": "^2.0.2", "cpy": "^7.0.1", @@ -60,7 +62,6 @@ "strip-ansi": "^4.0.0", "strong-log-transformer": "^2.1.0", "tempy": "^0.2.1", - "ts-loader": "^5.2.2", "typescript": "^3.3.3333", "unlazy-loader": "^0.1.3", "webpack": "^4.23.1", diff --git a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/package.json b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/package.json index df6ad1d3d6d9b..c1269fc7c037b 100644 --- a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/package.json +++ b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/package.json @@ -4,10 +4,11 @@ "private": true, "main": "./target/index.js", "devDependencies": { - "babel-cli": "^6.26.0", - "babel-preset-env": "^1.6.1" + "@babel/cli": "^7.2.3", + "@babel/core": "^7.3.4", + "@babel/preset-env": "^7.3.4" }, "scripts": { - "build": "babel --presets env --out-dir target src" + "build": "babel --presets=@babel/preset-env --out-dir target src" } } diff --git a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/package.json b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/package.json index 385aa59bffc7a..8b8225594c5ac 100644 --- a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/package.json +++ b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/package.json @@ -7,11 +7,12 @@ "@elastic/bar": "link:../bar" }, "devDependencies": { - "babel-cli": "^6.26.0", - "babel-preset-env": "^1.6.1", + "@babel/core": "^7.3.4", + "@babel/cli": "^7.2.3", + "@babel/preset-env": "^7.3.4", "moment": "2.20.1" }, "scripts": { - "build": "babel --presets env --out-dir target src" + "build": "babel --presets=@babel/preset-env --out-dir target src" } } diff --git a/packages/kbn-pm/src/production/integration_tests/__snapshots__/build_production_projects.test.ts.snap b/packages/kbn-pm/src/production/integration_tests/__snapshots__/build_production_projects.test.ts.snap index 94642340e0d9d..5049c692aae68 100644 --- a/packages/kbn-pm/src/production/integration_tests/__snapshots__/build_production_projects.test.ts.snap +++ b/packages/kbn-pm/src/production/integration_tests/__snapshots__/build_production_projects.test.ts.snap @@ -20,14 +20,15 @@ Array [ exports[`kbn-pm production builds and copies projects for production: packages/bar/package.json 1`] = ` Object { "devDependencies": Object { - "babel-cli": "^6.26.0", - "babel-preset-env": "^1.6.1", + "@babel/cli": "^7.2.3", + "@babel/core": "^7.3.4", + "@babel/preset-env": "^7.3.4", }, "main": "./target/index.js", "name": "@elastic/bar", "private": true, "scripts": Object { - "build": "babel --presets env --out-dir target src", + "build": "babel --presets=@babel/preset-env --out-dir target src", }, "version": "1.0.0", } @@ -47,15 +48,16 @@ Object { "@elastic/bar": "link:../bar", }, "devDependencies": Object { - "babel-cli": "^6.26.0", - "babel-preset-env": "^1.6.1", + "@babel/cli": "^7.2.3", + "@babel/core": "^7.3.4", + "@babel/preset-env": "^7.3.4", "moment": "2.20.1", }, "main": "./target/index.js", "name": "@elastic/foo", "private": true, "scripts": Object { - "build": "babel --presets env --out-dir target src", + "build": "babel --presets=@babel/preset-env --out-dir target src", }, "version": "1.0.0", } diff --git a/packages/kbn-pm/tsconfig.json b/packages/kbn-pm/tsconfig.json index f7c8cdab16782..2141c5502ae98 100644 --- a/packages/kbn-pm/tsconfig.json +++ b/packages/kbn-pm/tsconfig.json @@ -4,7 +4,7 @@ "dist" ], "include": [ - "./src/**/*.ts" + "./src/**/*.ts", ], "compilerOptions": { "types": [ diff --git a/packages/kbn-pm/webpack.config.js b/packages/kbn-pm/webpack.config.js index 1424850265e07..ff77d3cfb7e9c 100644 --- a/packages/kbn-pm/webpack.config.js +++ b/packages/kbn-pm/webpack.config.js @@ -44,15 +44,6 @@ module.exports = { { loader: 'babel-loader', }, - { - loader: 'ts-loader', - options: { - compilerOptions: { - // enable esnext modules so webpack can do its thing better - module: 'esnext', - }, - }, - }, ], exclude: /node_modules/, }, diff --git a/packages/kbn-test/babel.config.js b/packages/kbn-test/babel.config.js index 962d7d3e05c55..ff657603f4c8d 100644 --- a/packages/kbn-test/babel.config.js +++ b/packages/kbn-test/babel.config.js @@ -18,6 +18,6 @@ */ module.exports = { - presets: ['@kbn/babel-preset/node_preset_7'], + presets: ['@kbn/babel-preset/node_preset'], ignore: ['**/*.test.js'], }; diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index aa57d854e14cc..56790e8cb194e 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -10,9 +10,9 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { + "@babel/cli": "^7.2.3", "@kbn/babel-preset": "1.0.0", - "@kbn/dev-utils": "1.0.0", - "@babel/cli": "^7.2.3" + "@kbn/dev-utils": "1.0.0" }, "dependencies": { "chalk": "^2.4.1", diff --git a/packages/kbn-ui-framework/doc_site/src/index.js b/packages/kbn-ui-framework/doc_site/src/index.js index 094437d85e6b6..f53e8a608e1a1 100644 --- a/packages/kbn-ui-framework/doc_site/src/index.js +++ b/packages/kbn-ui-framework/doc_site/src/index.js @@ -19,7 +19,7 @@ require('./main.scss'); -import 'babel-polyfill'; +import '@babel/polyfill'; import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; diff --git a/packages/kbn-ui-framework/package.json b/packages/kbn-ui-framework/package.json index 87e586e90ec2f..f2b9c2f7e7139 100644 --- a/packages/kbn-ui-framework/package.json +++ b/packages/kbn-ui-framework/package.json @@ -26,16 +26,16 @@ "uuid": "3.0.1" }, "peerDependencies": { - "enzyme": "3.2.0", - "enzyme-adapter-react-16": "^1.1.1" + "enzyme": "^3.8.0", + "enzyme-adapter-react-16": "^1.9.1" }, "devDependencies": { + "@babel/core": "^7.3.4", + "@babel/polyfill": "^7.2.5", "@elastic/eui": "0.0.23", "@kbn/babel-preset": "1.0.0", "autoprefixer": "6.5.4", - "babel-core": "^6.26.3", - "babel-loader": "^7.1.5", - "babel-polyfill": "^6.26.0", + "babel-loader": "^8.0.5", "brace": "0.10.0", "chalk": "^2.4.1", "chokidar": "1.6.0", @@ -43,7 +43,7 @@ "expose-loader": "^0.7.5", "file-loader": "^2.0.0", "grunt": "1.0.3", - "grunt-babel": "^7.0.0", + "grunt-babel": "^8.0.0", "grunt-contrib-clean": "^1.1.0", "grunt-contrib-copy": "^1.0.0", "highlight.js": "9.0.0", diff --git a/src/core/public/core_system.test.mocks.ts b/src/core/public/core_system.test.mocks.ts new file mode 100644 index 0000000000000..cb3f45361d5f7 --- /dev/null +++ b/src/core/public/core_system.test.mocks.ts @@ -0,0 +1,92 @@ +/* + * 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 { basePathServiceMock } from './base_path/base_path_service.mock'; +import { chromeServiceMock } from './chrome/chrome_service.mock'; +import { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock'; +import { httpServiceMock } from './http/http_service.mock'; +import { i18nServiceMock } from './i18n/i18n_service.mock'; +import { injectedMetadataServiceMock } from './injected_metadata/injected_metadata_service.mock'; +import { legacyPlatformServiceMock } from './legacy/legacy_service.mock'; +import { notificationServiceMock } from './notifications/notifications_service.mock'; +import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; + +export const MockLegacyPlatformService = legacyPlatformServiceMock.create(); +export const LegacyPlatformServiceConstructor = jest + .fn() + .mockImplementation(() => MockLegacyPlatformService); +jest.doMock('./legacy', () => ({ + LegacyPlatformService: LegacyPlatformServiceConstructor, +})); + +export const MockInjectedMetadataService = injectedMetadataServiceMock.create(); +export const InjectedMetadataServiceConstructor = jest + .fn() + .mockImplementation(() => MockInjectedMetadataService); +jest.doMock('./injected_metadata', () => ({ + InjectedMetadataService: InjectedMetadataServiceConstructor, +})); + +export const MockFatalErrorsService = fatalErrorsServiceMock.create(); +export const FatalErrorsServiceConstructor = jest + .fn() + .mockImplementation(() => MockFatalErrorsService); +jest.doMock('./fatal_errors', () => ({ + FatalErrorsService: FatalErrorsServiceConstructor, +})); + +export const MockI18nService = i18nServiceMock.create(); +export const I18nServiceConstructor = jest.fn().mockImplementation(() => MockI18nService); +jest.doMock('./i18n', () => ({ + I18nService: I18nServiceConstructor, +})); + +export const MockNotificationsService = notificationServiceMock.create(); +export const NotificationServiceConstructor = jest + .fn() + .mockImplementation(() => MockNotificationsService); +jest.doMock('./notifications', () => ({ + NotificationsService: NotificationServiceConstructor, +})); + +export const MockHttpService = httpServiceMock.create(); +export const HttpServiceConstructor = jest.fn().mockImplementation(() => MockHttpService); +jest.doMock('./http', () => ({ + HttpService: HttpServiceConstructor, +})); + +export const MockBasePathService = basePathServiceMock.create(); +export const BasePathServiceConstructor = jest.fn().mockImplementation(() => MockBasePathService); +jest.doMock('./base_path', () => ({ + BasePathService: BasePathServiceConstructor, +})); + +export const MockUiSettingsService = uiSettingsServiceMock.create(); +export const UiSettingsServiceConstructor = jest + .fn() + .mockImplementation(() => MockUiSettingsService); +jest.doMock('./ui_settings', () => ({ + UiSettingsService: UiSettingsServiceConstructor, +})); + +export const MockChromeService = chromeServiceMock.create(); +export const ChromeServiceConstructor = jest.fn().mockImplementation(() => MockChromeService); +jest.doMock('./chrome', () => ({ + ChromeService: ChromeServiceConstructor, +})); diff --git a/src/core/public/core_system.test.ts b/src/core/public/core_system.test.ts index 9d9620e3b0853..3a8580127f15c 100644 --- a/src/core/public/core_system.test.ts +++ b/src/core/public/core_system.test.ts @@ -17,73 +17,26 @@ * under the License. */ -import { basePathServiceMock } from './base_path/base_path_service.mock'; -import { chromeServiceMock } from './chrome/chrome_service.mock'; -import { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock'; -import { httpServiceMock } from './http/http_service.mock'; -import { i18nServiceMock } from './i18n/i18n_service.mock'; -import { injectedMetadataServiceMock } from './injected_metadata/injected_metadata_service.mock'; -import { legacyPlatformServiceMock } from './legacy/legacy_service.mock'; -import { notificationServiceMock } from './notifications/notifications_service.mock'; -import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; - -const MockLegacyPlatformService = legacyPlatformServiceMock.create(); -const LegacyPlatformServiceConstructor = jest - .fn() - .mockImplementation(() => MockLegacyPlatformService); -jest.mock('./legacy', () => ({ - LegacyPlatformService: LegacyPlatformServiceConstructor, -})); - -const MockInjectedMetadataService = injectedMetadataServiceMock.create(); -const InjectedMetadataServiceConstructor = jest - .fn() - .mockImplementation(() => MockInjectedMetadataService); -jest.mock('./injected_metadata', () => ({ - InjectedMetadataService: InjectedMetadataServiceConstructor, -})); - -const MockFatalErrorsService = fatalErrorsServiceMock.create(); -const FatalErrorsServiceConstructor = jest.fn().mockImplementation(() => MockFatalErrorsService); -jest.mock('./fatal_errors', () => ({ - FatalErrorsService: FatalErrorsServiceConstructor, -})); - -const MockI18nService = i18nServiceMock.create(); -const I18nServiceConstructor = jest.fn().mockImplementation(() => MockI18nService); -jest.mock('./i18n', () => ({ - I18nService: I18nServiceConstructor, -})); - -const MockNotificationsService = notificationServiceMock.create(); -const NotificationServiceConstructor = jest.fn().mockImplementation(() => MockNotificationsService); -jest.mock('./notifications', () => ({ - NotificationsService: NotificationServiceConstructor, -})); - -const MockHttpService = httpServiceMock.create(); -const HttpServiceConstructor = jest.fn().mockImplementation(() => MockHttpService); -jest.mock('./http', () => ({ - HttpService: HttpServiceConstructor, -})); - -const MockBasePathService = basePathServiceMock.create(); -const BasePathServiceConstructor = jest.fn().mockImplementation(() => MockBasePathService); -jest.mock('./base_path', () => ({ - BasePathService: BasePathServiceConstructor, -})); - -const MockUiSettingsService = uiSettingsServiceMock.create(); -const UiSettingsServiceConstructor = jest.fn().mockImplementation(() => MockUiSettingsService); -jest.mock('./ui_settings', () => ({ - UiSettingsService: UiSettingsServiceConstructor, -})); - -const MockChromeService = chromeServiceMock.create(); -const ChromeServiceConstructor = jest.fn().mockImplementation(() => MockChromeService); -jest.mock('./chrome', () => ({ - ChromeService: ChromeServiceConstructor, -})); +import { + BasePathServiceConstructor, + ChromeServiceConstructor, + FatalErrorsServiceConstructor, + HttpServiceConstructor, + I18nServiceConstructor, + InjectedMetadataServiceConstructor, + LegacyPlatformServiceConstructor, + MockBasePathService, + MockChromeService, + MockFatalErrorsService, + MockHttpService, + MockI18nService, + MockInjectedMetadataService, + MockLegacyPlatformService, + MockNotificationsService, + MockUiSettingsService, + NotificationServiceConstructor, + UiSettingsServiceConstructor, +} from './core_system.test.mocks'; import { CoreSystem } from './core_system'; jest.spyOn(CoreSystem.prototype, 'stop'); diff --git a/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap b/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap index a58d0f6fc9c37..c6912764db2af 100644 --- a/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap +++ b/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap @@ -53,8 +53,7 @@ exports[`rendering render matches snapshot 1`] = ` body={

    diff --git a/src/core/public/fatal_errors/fatal_errors_service.test.mocks.ts b/src/core/public/fatal_errors/fatal_errors_service.test.mocks.ts new file mode 100644 index 0000000000000..b998817a1bfcc --- /dev/null +++ b/src/core/public/fatal_errors/fatal_errors_service.test.mocks.ts @@ -0,0 +1,25 @@ +/* + * 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 const mockRender = jest.fn(); +jest.mock('react-dom', () => { + return { + render: mockRender, + }; +}); diff --git a/src/core/public/fatal_errors/fatal_errors_service.test.ts b/src/core/public/fatal_errors/fatal_errors_service.test.ts index 6f3842fc4e0e9..b1ad92c8c2f62 100644 --- a/src/core/public/fatal_errors/fatal_errors_service.test.ts +++ b/src/core/public/fatal_errors/fatal_errors_service.test.ts @@ -24,12 +24,7 @@ expect.addSnapshotSerializer({ print: () => `Rx.Observable`, }); -const mockRender = jest.fn(); -jest.mock('react-dom', () => { - return { - render: mockRender, - }; -}); +import { mockRender } from './fatal_errors_service.test.mocks'; import { FatalErrorsService } from './fatal_errors_service'; diff --git a/src/core/public/notifications/toasts/toasts_service.test.mocks.ts b/src/core/public/notifications/toasts/toasts_service.test.mocks.ts new file mode 100644 index 0000000000000..90ea76c551564 --- /dev/null +++ b/src/core/public/notifications/toasts/toasts_service.test.mocks.ts @@ -0,0 +1,25 @@ +/* + * 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 const mockReactDomRender = jest.fn(); +export const mockReactDomUnmount = jest.fn(); +jest.mock('react-dom', () => ({ + render: mockReactDomRender, + unmountComponentAtNode: mockReactDomUnmount, +})); diff --git a/src/core/public/notifications/toasts/toasts_service.test.tsx b/src/core/public/notifications/toasts/toasts_service.test.tsx index d380ad5b77ea6..849fdda97f939 100644 --- a/src/core/public/notifications/toasts/toasts_service.test.tsx +++ b/src/core/public/notifications/toasts/toasts_service.test.tsx @@ -17,12 +17,7 @@ * under the License. */ -const mockReactDomRender = jest.fn(); -const mockReactDomUnmount = jest.fn(); -jest.mock('react-dom', () => ({ - render: mockReactDomRender, - unmountComponentAtNode: mockReactDomUnmount, -})); +import { mockReactDomRender, mockReactDomUnmount } from './toasts_service.test.mocks'; import { ToastsService } from './toasts_service'; import { ToastsSetup } from './toasts_start'; diff --git a/src/core/public/ui_settings/ui_settings_service.test.mocks.ts b/src/core/public/ui_settings/ui_settings_service.test.mocks.ts new file mode 100644 index 0000000000000..458a9efdea469 --- /dev/null +++ b/src/core/public/ui_settings/ui_settings_service.test.mocks.ts @@ -0,0 +1,57 @@ +/* + * 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. + */ + +function mockClass( + module: string, + Class: { new (...args: any[]): T }, + setup: (instance: any, args: any[]) => void +) { + const MockClass = jest.fn(function(this: any, ...args: any[]) { + setup(this, args); + }); + + // define the mock name which is used in some snapshots + MockClass.mockName(`Mock${Class.name}`); + + // define the class name for the MockClass which is used in other snapshots + Object.defineProperty(MockClass, 'name', { + value: `Mock${Class.name}`, + }); + + jest.doMock(module, () => ({ + [Class.name]: MockClass, + })); + + return MockClass; +} + +// Mock the UiSettingsApi class +import { UiSettingsApi } from './ui_settings_api'; +export const MockUiSettingsApi = mockClass('./ui_settings_api', UiSettingsApi, inst => { + inst.stop = jest.fn(); + inst.getLoadingCount$ = jest.fn().mockReturnValue({ + loadingCountObservable: true, + }); +}); + +// Mock the UiSettingsClient class +import { UiSettingsClient } from './ui_settings_client'; +export const MockUiSettingsClient = mockClass('./ui_settings_client', UiSettingsClient, inst => { + inst.stop = jest.fn(); +}); diff --git a/src/core/public/ui_settings/ui_settings_service.test.ts b/src/core/public/ui_settings/ui_settings_service.test.ts index e58b517984fc5..f1bfab2981d6e 100644 --- a/src/core/public/ui_settings/ui_settings_service.test.ts +++ b/src/core/public/ui_settings/ui_settings_service.test.ts @@ -17,44 +17,7 @@ * under the License. */ -function mockClass( - module: string, - Class: { new (...args: any[]): T }, - setup: (instance: any, args: any[]) => void -) { - const MockClass = jest.fn(function(this: any, ...args: any[]) { - setup(this, args); - }); - - // define the mock name which is used in some snapshots - MockClass.mockName(`Mock${Class.name}`); - - // define the class name for the MockClass which is used in other snapshots - Object.defineProperty(MockClass, 'name', { - value: `Mock${Class.name}`, - }); - - jest.mock(module, () => ({ - [Class.name]: MockClass, - })); - - return MockClass; -} - -// Mock the UiSettingsApi class -import { UiSettingsApi } from './ui_settings_api'; -const MockUiSettingsApi = mockClass('./ui_settings_api', UiSettingsApi, inst => { - inst.stop = jest.fn(); - inst.getLoadingCount$ = jest.fn().mockReturnValue({ - loadingCountObservable: true, - }); -}); - -// Mock the UiSettingsClient class -import { UiSettingsClient } from './ui_settings_client'; -const MockUiSettingsClient = mockClass('./ui_settings_client', UiSettingsClient, inst => { - inst.stop = jest.fn(); -}); +import { MockUiSettingsApi, MockUiSettingsClient } from './ui_settings_service.test.mocks'; import { basePathServiceMock } from '../base_path/base_path_service.mock'; import { httpServiceMock } from '../http/http_service.mock'; diff --git a/src/core/server/config/config_service.mock.ts b/src/core/server/config/config_service.mock.ts index d9f460905fc43..92b0f117b1a02 100644 --- a/src/core/server/config/config_service.mock.ts +++ b/src/core/server/config/config_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { BehaviorSubject } from 'rxjs'; import { ObjectToConfigAdapter } from './object_to_config_adapter'; diff --git a/src/core/server/config/config_service.test.mocks.ts b/src/core/server/config/config_service.test.mocks.ts new file mode 100644 index 0000000000000..8fa1ec997d625 --- /dev/null +++ b/src/core/server/config/config_service.test.mocks.ts @@ -0,0 +1,21 @@ +/* + * 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 const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); +jest.mock('../../../../package.json', () => mockPackage); diff --git a/src/core/server/config/config_service.test.ts b/src/core/server/config/config_service.test.ts index 7a10d4992e2c2..a054786c80f7d 100644 --- a/src/core/server/config/config_service.test.ts +++ b/src/core/server/config/config_service.test.ts @@ -22,8 +22,7 @@ import { BehaviorSubject } from 'rxjs'; import { first } from 'rxjs/operators'; -const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../../package.json', () => mockPackage); +import { mockPackage } from './config_service.test.mocks'; import { schema, Type, TypeOf } from '@kbn/config-schema'; diff --git a/src/core/server/config/env.test.mocks.ts b/src/core/server/config/env.test.mocks.ts new file mode 100644 index 0000000000000..be65aa1727076 --- /dev/null +++ b/src/core/server/config/env.test.mocks.ts @@ -0,0 +1,33 @@ +/* + * 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. + */ + +jest.mock('process', () => ({ + cwd() { + return '/test/cwd'; + }, +})); + +jest.mock('path', () => ({ + resolve(...pathSegments: string[]) { + return pathSegments.join('/'); + }, +})); + +export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); +jest.mock('../../../../package.json', () => mockPackage); diff --git a/src/core/server/config/env.test.ts b/src/core/server/config/env.test.ts index 3c251b7339e49..13bd05c3b1c84 100644 --- a/src/core/server/config/env.test.ts +++ b/src/core/server/config/env.test.ts @@ -17,20 +17,7 @@ * under the License. */ -jest.mock('process', () => ({ - cwd() { - return '/test/cwd'; - }, -})); - -jest.mock('path', () => ({ - resolve(...pathSegments: string[]) { - return pathSegments.join('/'); - }, -})); - -const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../../package.json', () => mockPackage); +import { mockPackage } from './env.test.mocks'; import { Env } from '.'; import { getEnvOptions } from './__mocks__/env'; diff --git a/src/core/server/config/raw_config_service.test.mocks.ts b/src/core/server/config/raw_config_service.test.mocks.ts new file mode 100644 index 0000000000000..be43b0f64e658 --- /dev/null +++ b/src/core/server/config/raw_config_service.test.mocks.ts @@ -0,0 +1,24 @@ +/* + * 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 const mockGetConfigFromFiles = jest.fn(); + +jest.mock('./read_config', () => ({ + getConfigFromFiles: mockGetConfigFromFiles, +})); diff --git a/src/core/server/config/raw_config_service.test.ts b/src/core/server/config/raw_config_service.test.ts index 0cd0dc45cd939..361cef0d042ea 100644 --- a/src/core/server/config/raw_config_service.test.ts +++ b/src/core/server/config/raw_config_service.test.ts @@ -17,11 +17,7 @@ * under the License. */ -const mockGetConfigFromFiles = jest.fn(); - -jest.mock('./read_config', () => ({ - getConfigFromFiles: mockGetConfigFromFiles, -})); +import { mockGetConfigFromFiles } from './raw_config_service.test.mocks'; import { first } from 'rxjs/operators'; import { RawConfigService } from '.'; diff --git a/src/core/server/elasticsearch/cluster_client.test.mocks.ts b/src/core/server/elasticsearch/cluster_client.test.mocks.ts new file mode 100644 index 0000000000000..4a8553d1d5f99 --- /dev/null +++ b/src/core/server/elasticsearch/cluster_client.test.mocks.ts @@ -0,0 +1,35 @@ +/* + * 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 const MockClient = jest.fn(); +jest.mock('elasticsearch', () => ({ + // Jest types don't include `requireActual` right now. + ...jest.requireActual('elasticsearch'), + Client: MockClient, +})); + +export const MockScopedClusterClient = jest.fn(); +jest.mock('./scoped_cluster_client', () => ({ + ScopedClusterClient: MockScopedClusterClient, +})); + +export const mockParseElasticsearchClientConfig = jest.fn(); +jest.mock('./elasticsearch_client_config', () => ({ + parseElasticsearchClientConfig: mockParseElasticsearchClientConfig, +})); diff --git a/src/core/server/elasticsearch/cluster_client.test.ts b/src/core/server/elasticsearch/cluster_client.test.ts index da511c282981e..30a1ac7a038ed 100644 --- a/src/core/server/elasticsearch/cluster_client.test.ts +++ b/src/core/server/elasticsearch/cluster_client.test.ts @@ -19,22 +19,11 @@ import { ElasticsearchConfig } from './elasticsearch_config'; -const MockClient = jest.fn(); -jest.mock('elasticsearch', () => ({ - // Jest types don't include `requireActual` right now. - ...(jest as any).requireActual('elasticsearch'), - Client: MockClient, -})); - -const MockScopedClusterClient = jest.fn(); -jest.mock('./scoped_cluster_client', () => ({ - ScopedClusterClient: MockScopedClusterClient, -})); - -const mockParseElasticsearchClientConfig = jest.fn(); -jest.mock('./elasticsearch_client_config', () => ({ - parseElasticsearchClientConfig: mockParseElasticsearchClientConfig, -})); +import { + MockClient, + mockParseElasticsearchClientConfig, + MockScopedClusterClient, +} from './cluster_client.test.mocks'; import { errors } from 'elasticsearch'; import { get } from 'lodash'; diff --git a/src/dev/jest/ts_transform.js b/src/core/server/elasticsearch/elasticsearch_client_config.test.mocks.ts similarity index 88% rename from src/dev/jest/ts_transform.js rename to src/core/server/elasticsearch/elasticsearch_client_config.test.mocks.ts index f097ed2f8076a..f6c6079822cb5 100644 --- a/src/dev/jest/ts_transform.js +++ b/src/core/server/elasticsearch/elasticsearch_client_config.test.mocks.ts @@ -17,5 +17,5 @@ * under the License. */ -require('../../setup_node_env'); -module.exports = require('./ts_transform.ts'); +export const mockReadFileSync = jest.fn(); +jest.mock('fs', () => ({ readFileSync: mockReadFileSync })); diff --git a/src/core/server/elasticsearch/elasticsearch_client_config.test.ts b/src/core/server/elasticsearch/elasticsearch_client_config.test.ts index f2eb30f736403..64fb41cb3e4e5 100644 --- a/src/core/server/elasticsearch/elasticsearch_client_config.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_client_config.test.ts @@ -17,8 +17,7 @@ * under the License. */ -const mockReadFileSync = jest.fn(); -jest.mock('fs', () => ({ readFileSync: mockReadFileSync })); +import { mockReadFileSync } from './elasticsearch_client_config.test.mocks'; import { duration } from 'moment'; import { loggingServiceMock } from '../logging/logging_service.mock'; @@ -67,7 +66,7 @@ Object { }); test('parses fully specified config', () => { - mockReadFileSync.mockImplementation(path => `content-of-${path}`); + mockReadFileSync.mockImplementation((path: string) => `content-of-${path}`); const elasticsearchConfig: ElasticsearchClientConfig = { apiVersion: 'v7.0.0', @@ -607,7 +606,7 @@ Object { }); test('#ignoreCertAndKey = true', () => { - mockReadFileSync.mockImplementation(path => `content-of-${path}`); + mockReadFileSync.mockImplementation((path: string) => `content-of-${path}`); expect( parseElasticsearchClientConfig( diff --git a/src/core/server/elasticsearch/elasticsearch_service.mock.ts b/src/core/server/elasticsearch/elasticsearch_service.mock.ts index bbd7fda86c5e4..57157adc2fac5 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.mock.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { BehaviorSubject } from 'rxjs'; import { ClusterClient } from './cluster_client'; import { ElasticsearchConfig } from './elasticsearch_config'; diff --git a/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts b/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts new file mode 100644 index 0000000000000..e87913a3c5e4f --- /dev/null +++ b/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts @@ -0,0 +1,21 @@ +/* + * 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 const MockClusterClient = jest.fn(); +jest.mock('./cluster_client', () => ({ ClusterClient: MockClusterClient })); diff --git a/src/core/server/elasticsearch/elasticsearch_service.test.ts b/src/core/server/elasticsearch/elasticsearch_service.test.ts index f880e318e7173..0697d9152f0a9 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.test.ts @@ -19,8 +19,7 @@ import { first } from 'rxjs/operators'; -const MockClusterClient = jest.fn(); -jest.mock('./cluster_client', () => ({ ClusterClient: MockClusterClient })); +import { MockClusterClient } from './elasticsearch_service.test.mocks'; import { BehaviorSubject, combineLatest } from 'rxjs'; import { Config, ConfigService, Env, ObjectToConfigAdapter } from '../config'; diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index f246ff6634b31..bc9a42b26fdff 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { Server, ServerOptions } from 'hapi'; import { HttpService } from './http_service'; diff --git a/src/core/server/http/http_service.test.mocks.ts b/src/core/server/http/http_service.test.mocks.ts new file mode 100644 index 0000000000000..a0d7ff5069eb0 --- /dev/null +++ b/src/core/server/http/http_service.test.mocks.ts @@ -0,0 +1,24 @@ +/* + * 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 const mockHttpServer = jest.fn(); + +jest.mock('./http_server', () => ({ + HttpServer: mockHttpServer, +})); diff --git a/src/core/server/http/http_service.test.ts b/src/core/server/http/http_service.test.ts index 6ed3d13221dc2..6c38162a0b7f9 100644 --- a/src/core/server/http/http_service.test.ts +++ b/src/core/server/http/http_service.test.ts @@ -17,11 +17,7 @@ * under the License. */ -const mockHttpServer = jest.fn(); - -jest.mock('./http_server', () => ({ - HttpServer: mockHttpServer, -})); +import { mockHttpServer } from './http_service.test.mocks'; import { noop } from 'lodash'; import { BehaviorSubject } from 'rxjs'; diff --git a/src/core/server/index.test.mocks.ts b/src/core/server/index.test.mocks.ts new file mode 100644 index 0000000000000..c25772ea46de4 --- /dev/null +++ b/src/core/server/index.test.mocks.ts @@ -0,0 +1,40 @@ +/* + * 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 { httpServiceMock } from './http/http_service.mock'; +export const httpService = httpServiceMock.create(); +jest.doMock('./http/http_service', () => ({ + HttpService: jest.fn(() => httpService), +})); + +export const mockPluginsService = { setup: jest.fn(), stop: jest.fn() }; +jest.doMock('./plugins/plugins_service', () => ({ + PluginsService: jest.fn(() => mockPluginsService), +})); + +import { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.mock'; +export const elasticsearchService = elasticsearchServiceMock.create(); +jest.doMock('./elasticsearch/elasticsearch_service', () => ({ + ElasticsearchService: jest.fn(() => elasticsearchService), +})); + +export const mockLegacyService = { setup: jest.fn(), stop: jest.fn() }; +jest.mock('./legacy/legacy_service', () => ({ + LegacyService: jest.fn(() => mockLegacyService), +})); diff --git a/src/core/server/legacy/__snapshots__/legacy_service.test.ts.snap b/src/core/server/legacy/__snapshots__/legacy_service.test.ts.snap index 050184b1f1d52..76d53b4b1cc5d 100644 --- a/src/core/server/legacy/__snapshots__/legacy_service.test.ts.snap +++ b/src/core/server/legacy/__snapshots__/legacy_service.test.ts.snap @@ -28,6 +28,7 @@ Array [ "valueInBytes": 1073741824, }, }, + "httpsAgent": undefined, "log": Object { "context": Array [ "server", @@ -52,6 +53,7 @@ Array [ "trace": [MockFunction], "warn": [MockFunction], }, + "server": undefined, }, ], ] diff --git a/src/core/server/logging/appenders/appenders.test.mocks.ts b/src/core/server/logging/appenders/appenders.test.mocks.ts new file mode 100644 index 0000000000000..551a4ac1bedc3 --- /dev/null +++ b/src/core/server/logging/appenders/appenders.test.mocks.ts @@ -0,0 +1,29 @@ +/* + * 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 const mockCreateLayout = jest.fn(); +jest.mock('../layouts/layouts', () => { + const { schema } = require('@kbn/config-schema'); + return { + Layouts: { + configSchema: schema.object({ kind: schema.literal('mock') }), + create: mockCreateLayout, + }, + }; +}); diff --git a/src/core/server/logging/appenders/appenders.test.ts b/src/core/server/logging/appenders/appenders.test.ts index df528f4c58cd5..7cfd2158be338 100644 --- a/src/core/server/logging/appenders/appenders.test.ts +++ b/src/core/server/logging/appenders/appenders.test.ts @@ -17,16 +17,7 @@ * under the License. */ -const mockCreateLayout = jest.fn(); -jest.mock('../layouts/layouts', () => { - const { schema } = require('@kbn/config-schema'); - return { - Layouts: { - configSchema: schema.object({ kind: schema.literal('mock') }), - create: mockCreateLayout, - }, - }; -}); +import { mockCreateLayout } from './appenders.test.mocks'; import { LegacyAppender } from '../../legacy/logging/appenders/legacy_appender'; import { Appenders } from './appenders'; diff --git a/src/core/server/logging/appenders/file/file_appender.test.mocks.ts b/src/core/server/logging/appenders/file/file_appender.test.mocks.ts new file mode 100644 index 0000000000000..a4e4532882f52 --- /dev/null +++ b/src/core/server/logging/appenders/file/file_appender.test.mocks.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +jest.mock('../../layouts/layouts', () => { + const { schema } = require('@kbn/config-schema'); + return { + Layouts: { + configSchema: schema.object({ + kind: schema.literal('mock'), + }), + }, + }; +}); + +export const mockCreateWriteStream = jest.fn(); +jest.mock('fs', () => ({ createWriteStream: mockCreateWriteStream })); diff --git a/src/core/server/logging/appenders/file/file_appender.test.ts b/src/core/server/logging/appenders/file/file_appender.test.ts index 1d9ef33995955..fccca629f7d60 100644 --- a/src/core/server/logging/appenders/file/file_appender.test.ts +++ b/src/core/server/logging/appenders/file/file_appender.test.ts @@ -17,19 +17,7 @@ * under the License. */ -jest.mock('../../layouts/layouts', () => { - const { schema } = require('@kbn/config-schema'); - return { - Layouts: { - configSchema: schema.object({ - kind: schema.literal('mock'), - }), - }, - }; -}); - -const mockCreateWriteStream = jest.fn(); -jest.mock('fs', () => ({ createWriteStream: mockCreateWriteStream })); +import { mockCreateWriteStream } from './file_appender.test.mocks'; import { LogLevel } from '../../log_level'; import { LogRecord } from '../../log_record'; diff --git a/src/core/server/plugins/discovery/plugin_discovery.test.mocks.ts b/src/core/server/plugins/discovery/plugin_discovery.test.mocks.ts new file mode 100644 index 0000000000000..d92465e4dd497 --- /dev/null +++ b/src/core/server/plugins/discovery/plugin_discovery.test.mocks.ts @@ -0,0 +1,30 @@ +/* + * 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 const mockReaddir = jest.fn(); +export const mockReadFile = jest.fn(); +export const mockStat = jest.fn(); +jest.mock('fs', () => ({ + readdir: mockReaddir, + readFile: mockReadFile, + stat: mockStat, +})); + +export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); +jest.mock('../../../../../package.json', () => mockPackage); diff --git a/src/core/server/plugins/discovery/plugin_discovery.test.ts b/src/core/server/plugins/discovery/plugin_discovery.test.ts index 266ad1780d47f..ac02a21cbe7a7 100644 --- a/src/core/server/plugins/discovery/plugin_discovery.test.ts +++ b/src/core/server/plugins/discovery/plugin_discovery.test.ts @@ -17,17 +17,7 @@ * under the License. */ -const mockReaddir = jest.fn(); -const mockReadFile = jest.fn(); -const mockStat = jest.fn(); -jest.mock('fs', () => ({ - readdir: mockReaddir, - readFile: mockReadFile, - stat: mockStat, -})); - -const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../../../package.json', () => mockPackage); +import { mockPackage, mockReaddir, mockReadFile, mockStat } from './plugin_discovery.test.mocks'; import { resolve } from 'path'; import { BehaviorSubject } from 'rxjs'; diff --git a/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts b/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts new file mode 100644 index 0000000000000..eb8dc1e609582 --- /dev/null +++ b/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts @@ -0,0 +1,22 @@ +/* + * 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 const mockReadFile = jest.fn(); +const mockStat = jest.fn(); +jest.mock('fs', () => ({ readFile: mockReadFile, stat: mockStat })); diff --git a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts index d6012e4a5e2e4..082cd82e5e1f0 100644 --- a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts +++ b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts @@ -19,9 +19,7 @@ import { PluginDiscoveryErrorType } from './plugin_discovery_error'; -const mockReadFile = jest.fn(); -const mockStat = jest.fn(); -jest.mock('fs', () => ({ readFile: mockReadFile, stat: mockStat })); +import { mockReadFile } from './plugin_manifest_parser.test.mocks'; import { resolve } from 'path'; import { parseManifest } from './plugin_manifest_parser'; diff --git a/src/core/server/plugins/plugin.test.ts b/src/core/server/plugins/plugin.test.ts index 284e9e10cb7b8..2f2a73668a59d 100644 --- a/src/core/server/plugins/plugin.test.ts +++ b/src/core/server/plugins/plugin.test.ts @@ -30,15 +30,15 @@ import { createPluginInitializerContext, createPluginSetupContext } from './plug const mockPluginInitializer = jest.fn(); const logger = loggingServiceMock.create(); -jest.mock( +jest.doMock( join('plugin-with-initializer-path', 'server'), () => ({ plugin: mockPluginInitializer }), { virtual: true } ); -jest.mock(join('plugin-without-initializer-path', 'server'), () => ({}), { +jest.doMock(join('plugin-without-initializer-path', 'server'), () => ({}), { virtual: true, }); -jest.mock(join('plugin-with-wrong-initializer-path', 'server'), () => ({ plugin: {} }), { +jest.doMock(join('plugin-with-wrong-initializer-path', 'server'), () => ({ plugin: {} }), { virtual: true, }); diff --git a/src/core/server/plugins/plugins_service.test.mocks.ts b/src/core/server/plugins/plugins_service.test.mocks.ts new file mode 100644 index 0000000000000..13b492e382d67 --- /dev/null +++ b/src/core/server/plugins/plugins_service.test.mocks.ts @@ -0,0 +1,26 @@ +/* + * 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 const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); +jest.mock('../../../legacy/utils/package_json', () => ({ pkg: mockPackage })); + +export const mockDiscover = jest.fn(); +jest.mock('./discovery/plugins_discovery', () => ({ discover: mockDiscover })); + +jest.mock('./plugins_system'); diff --git a/src/core/server/plugins/plugins_service.test.ts b/src/core/server/plugins/plugins_service.test.ts index 553cb8a031389..2a3ce3a4f88d5 100644 --- a/src/core/server/plugins/plugins_service.test.ts +++ b/src/core/server/plugins/plugins_service.test.ts @@ -17,13 +17,7 @@ * under the License. */ -const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../legacy/utils/package_json', () => ({ pkg: mockPackage })); - -const mockDiscover = jest.fn(); -jest.mock('./discovery/plugins_discovery', () => ({ discover: mockDiscover })); - -jest.mock('./plugins_system'); +import { mockDiscover, mockPackage } from './plugins_service.test.mocks'; import { resolve } from 'path'; import { BehaviorSubject, from } from 'rxjs'; diff --git a/src/core/server/plugins/plugins_system.test.mocks.ts b/src/core/server/plugins/plugins_system.test.mocks.ts new file mode 100644 index 0000000000000..9bcbba892fa2a --- /dev/null +++ b/src/core/server/plugins/plugins_system.test.mocks.ts @@ -0,0 +1,23 @@ +/* + * 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 const mockCreatePluginSetupContext = jest.fn(); +jest.mock('./plugin_context', () => ({ + createPluginSetupContext: mockCreatePluginSetupContext, +})); diff --git a/src/core/server/plugins/plugins_system.test.ts b/src/core/server/plugins/plugins_system.test.ts index 2df8b8301b0ef..3202a7697bd60 100644 --- a/src/core/server/plugins/plugins_system.test.ts +++ b/src/core/server/plugins/plugins_system.test.ts @@ -17,16 +17,12 @@ * under the License. */ -import { CoreContext } from '../core_context'; - -const mockCreatePluginSetupContext = jest.fn(); -jest.mock('./plugin_context', () => ({ - createPluginSetupContext: mockCreatePluginSetupContext, -})); +import { mockCreatePluginSetupContext } from './plugins_system.test.mocks'; import { BehaviorSubject } from 'rxjs'; import { Config, ConfigService, Env, ObjectToConfigAdapter } from '../config'; import { getEnvOptions } from '../config/__mocks__/env'; +import { CoreContext } from '../core_context'; import { elasticsearchServiceMock } from '../elasticsearch/elasticsearch_service.mock'; import { loggingServiceMock } from '../logging/logging_service.mock'; import { Plugin, PluginName } from './plugin'; diff --git a/src/core/server/root/index.test.mocks.ts b/src/core/server/root/index.test.mocks.ts new file mode 100644 index 0000000000000..602fa2368a766 --- /dev/null +++ b/src/core/server/root/index.test.mocks.ts @@ -0,0 +1,33 @@ +/* + * 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 { loggingServiceMock } from '../logging/logging_service.mock'; +export const logger = loggingServiceMock.create(); +jest.doMock('../logging', () => ({ + LoggingService: jest.fn(() => logger), +})); + +import { configServiceMock } from '../config/config_service.mock'; +export const configService = configServiceMock.create(); +jest.doMock('../config/config_service', () => ({ + ConfigService: jest.fn(() => configService), +})); + +export const mockServer = { setup: jest.fn(), stop: jest.fn() }; +jest.mock('../server', () => ({ Server: jest.fn(() => mockServer) })); diff --git a/src/core/server/root/index.test.ts b/src/core/server/root/index.test.ts index b5915debfe6a4..4eba2133dce28 100644 --- a/src/core/server/root/index.test.ts +++ b/src/core/server/root/index.test.ts @@ -17,20 +17,7 @@ * under the License. */ -import { loggingServiceMock } from '../logging/logging_service.mock'; -const logger = loggingServiceMock.create(); -jest.mock('../logging', () => ({ - LoggingService: jest.fn(() => logger), -})); - -import { configServiceMock } from '../config/config_service.mock'; -const configService = configServiceMock.create(); -jest.mock('../config/config_service', () => ({ - ConfigService: jest.fn(() => configService), -})); - -const mockServer = { setup: jest.fn(), stop: jest.fn() }; -jest.mock('../server', () => ({ Server: jest.fn(() => mockServer) })); +import { configService, logger, mockServer } from './index.test.mocks'; import { BehaviorSubject } from 'rxjs'; import { filter, first } from 'rxjs/operators'; diff --git a/src/core/server/server.test.ts b/src/core/server/server.test.ts index a3bfa8db21c44..cbfdbbc3bc00d 100644 --- a/src/core/server/server.test.ts +++ b/src/core/server/server.test.ts @@ -16,27 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import { httpServiceMock } from './http/http_service.mock'; -const httpService = httpServiceMock.create(); -jest.mock('./http/http_service', () => ({ - HttpService: jest.fn(() => httpService), -})); - -const mockPluginsService = { setup: jest.fn(), stop: jest.fn() }; -jest.mock('./plugins/plugins_service', () => ({ - PluginsService: jest.fn(() => mockPluginsService), -})); - -import { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.mock'; -const elasticsearchService = elasticsearchServiceMock.create(); -jest.mock('./elasticsearch/elasticsearch_service', () => ({ - ElasticsearchService: jest.fn(() => elasticsearchService), -})); - -const mockLegacyService = { setup: jest.fn(), stop: jest.fn() }; -jest.mock('./legacy/legacy_service', () => ({ - LegacyService: jest.fn(() => mockLegacyService), -})); + +import { + elasticsearchService, + httpService, + mockLegacyService, + mockPluginsService, +} from './index.test.mocks'; import { BehaviorSubject } from 'rxjs'; import { Env } from './config'; diff --git a/src/dev/build/build_distributables.js b/src/dev/build/build_distributables.js index cda00064162f2..bb450dcd006bc 100644 --- a/src/dev/build/build_distributables.js +++ b/src/dev/build/build_distributables.js @@ -47,8 +47,8 @@ import { RemovePackageJsonDepsTask, RemoveWorkspacesTask, TranspileBabelTask, - TranspileTypescriptTask, TranspileScssTask, + TypecheckTypescriptTask, UpdateLicenseFileTask, VerifyEnvTask, VerifyExistingNodeBuildsTask, @@ -107,15 +107,14 @@ export async function buildDistributables(options) { * run platform-generic build tasks */ await run(CopySourceTask); + await run(TypecheckTypescriptTask); await run(CreateEmptyDirsAndFilesTask); await run(CreateReadmeTask); await run(TranspileBabelTask); - await run(TranspileTypescriptTask); await run(BuildPackagesTask); await run(CreatePackageJsonTask); await run(InstallDependenciesTask); await run(RemoveWorkspacesTask); - await run(CleanTypescriptTask); await run(CleanPackagesTask); await run(CreateNoticeFileTask); await run(UpdateLicenseFileTask); @@ -123,6 +122,7 @@ export async function buildDistributables(options) { await run(TranspileScssTask); await run(OptimizeBuildTask); await run(CleanClientModulesOnDLLTask); + await run(CleanTypescriptTask); await run(CleanExtraFilesFromModulesTask); await run(CleanEmptyFoldersTask); diff --git a/src/dev/build/tasks/copy_source_task.js b/src/dev/build/tasks/copy_source_task.js index 18ca6492f08c3..01b31b51a060d 100644 --- a/src/dev/build/tasks/copy_source_task.js +++ b/src/dev/build/tasks/copy_source_task.js @@ -28,7 +28,8 @@ export const CopySourceTask = { select: [ 'yarn.lock', 'src/**', - '!src/**/*.test.{js,ts,tsx}', + '!src/**/*.{test,test.mocks,mock}.{js,ts,tsx}', + '!src/**/mocks.ts', // special file who imports .mock files '!src/**/{__tests__,__snapshots__}/**', '!src/test_utils/**', '!src/fixtures/**', diff --git a/src/dev/build/tasks/index.js b/src/dev/build/tasks/index.js index ecf86d6af23eb..acf4680fd6f42 100644 --- a/src/dev/build/tasks/index.js +++ b/src/dev/build/tasks/index.js @@ -33,7 +33,7 @@ export * from './notice_file_task'; export * from './optimize_task'; export * from './os_packages'; export * from './transpile_babel_task'; -export * from './transpile_typescript_task'; +export * from './typecheck_typescript_task'; export * from './transpile_scss_task'; export * from './verify_env_task'; export * from './write_sha_sums_task'; diff --git a/src/dev/build/tasks/transpile_babel_task.js b/src/dev/build/tasks/transpile_babel_task.js index 1ea3d81583918..c6d762be9d732 100644 --- a/src/dev/build/tasks/transpile_babel_task.js +++ b/src/dev/build/tasks/transpile_babel_task.js @@ -22,31 +22,59 @@ import vfs from 'vinyl-fs'; import { createPromiseFromStreams } from '../../../legacy/utils'; +const transpileWithBabel = async (srcGlobs, build, presets) => { + const buildRoot = build.resolvePath(); + + await createPromiseFromStreams([ + vfs.src( + srcGlobs.concat([ + '!**/*.d.ts', + '!packages/**', + '!**/node_modules/**', + '!**/bower_components/**', + '!**/__tests__/**', + ]), + { + cwd: buildRoot, + } + ), + + gulpBabel({ + babelrc: false, + presets, + }), + + vfs.dest(buildRoot), + ]); +}; + export const TranspileBabelTask = { description: 'Transpiling sources with babel', async run(config, log, build) { - await createPromiseFromStreams([ - vfs.src( - [ - '**/*.js', - '!packages/**', - '!**/public/**', - '!**/node_modules/**', - '!**/bower_components/**', - '!**/__tests__/**', - ], - { - cwd: build.resolvePath(), - } - ), - - gulpBabel({ - babelrc: false, - presets: [require.resolve('@kbn/babel-preset/node_preset')], - }), - - vfs.dest(build.resolvePath()), - ]); + // Transpile server code + await transpileWithBabel( + [ + '**/*.{js,ts,tsx}', + '!**/public/**', + ], + build, + [ + require.resolve('@kbn/babel-preset/node_preset') + ] + ); + + // Transpile client code + // NOTE: For the client, as we have the optimizer, we are only + // pre-transpiling the typescript based files + await transpileWithBabel( + [ + '**/public/**/*.{ts,tsx}', + ], + build, + [ + require.resolve('@kbn/babel-preset/webpack_preset') + ] + ); }, }; diff --git a/src/dev/build/tasks/transpile_typescript_task.js b/src/dev/build/tasks/typecheck_typescript_task.js similarity index 85% rename from src/dev/build/tasks/transpile_typescript_task.js rename to src/dev/build/tasks/typecheck_typescript_task.js index 735d6c17afec5..bbdc5f69be8b4 100644 --- a/src/dev/build/tasks/transpile_typescript_task.js +++ b/src/dev/build/tasks/typecheck_typescript_task.js @@ -20,22 +20,13 @@ import { exec, write } from '../lib'; import { Project } from '../../typescript'; -export const TranspileTypescriptTask = { - description: 'Transpiling sources with typescript compiler', +export const TypecheckTypescriptTask = { + description: 'Typechecking sources with typescript compiler', async run(config, log, build) { // these projects are built in the build folder - const defaultProject = new Project(build.resolvePath('tsconfig.json')); const browserProject = new Project(build.resolvePath('tsconfig.browser.json')); - - // update the default config to exclude **/public/**/* files - await write(defaultProject.tsConfigPath, JSON.stringify({ - ...defaultProject.config, - exclude: [ - ...defaultProject.config.exclude, - 'src/**/public/**/*' - ] - })); + const defaultProject = new Project(build.resolvePath('tsconfig.json')); // update the browser config file to include **/public/**/* files await write(browserProject.tsConfigPath, JSON.stringify({ @@ -47,21 +38,28 @@ export const TranspileTypescriptTask = { ] })); + // update the default config to exclude **/public/**/* files + await write(defaultProject.tsConfigPath, JSON.stringify({ + ...defaultProject.config, + exclude: [ + ...defaultProject.config.exclude, + 'src/**/public/**/*' + ] + })); + const projects = [ - // Browser needs to be compiled before server code so that any shared code - // is compiled to the lowest common denominator (server's CommonJS format) - // which can be supported by both environments. browserProject.tsConfigPath, defaultProject.tsConfigPath, ]; // compile each typescript config file for (const tsConfigPath of projects) { - log.info(`Compiling`, tsConfigPath, 'project'); + log.info(`Typechecking`, tsConfigPath, 'project'); await exec( log, require.resolve('typescript/bin/tsc'), [ + '--noEmit', '--pretty', 'true', '--project', tsConfigPath, ], diff --git a/src/dev/i18n/integrate_locale_files.test.mocks.ts b/src/dev/i18n/integrate_locale_files.test.mocks.ts new file mode 100644 index 0000000000000..e84ca068c067e --- /dev/null +++ b/src/dev/i18n/integrate_locale_files.test.mocks.ts @@ -0,0 +1,27 @@ +/* + * 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 const mockWriteFileAsync = jest.fn(); +export const mockMakeDirAsync = jest.fn(); +jest.mock('./utils', () => ({ + // Jest typings don't define `requireActual` for some reason. + ...(jest as any).requireActual('./utils'), + writeFileAsync: mockWriteFileAsync, + makeDirAsync: mockMakeDirAsync, +})); diff --git a/src/dev/i18n/integrate_locale_files.test.ts b/src/dev/i18n/integrate_locale_files.test.ts index 050f16f3d3344..7d7d1ba744684 100644 --- a/src/dev/i18n/integrate_locale_files.test.ts +++ b/src/dev/i18n/integrate_locale_files.test.ts @@ -17,14 +17,7 @@ * under the License. */ -const mockWriteFileAsync = jest.fn(); -const mockMakeDirAsync = jest.fn(); -jest.mock('./utils', () => ({ - // Jest typings don't define `requireActual` for some reason. - ...(jest as any).requireActual('./utils'), - writeFileAsync: mockWriteFileAsync, - makeDirAsync: mockMakeDirAsync, -})); +import { mockMakeDirAsync, mockWriteFileAsync } from './integrate_locale_files.test.mocks'; import path from 'path'; import { integrateLocaleFiles, verifyMessages } from './integrate_locale_files'; diff --git a/src/dev/jest/babel_transform.js b/src/dev/jest/babel_transform.js index 7bdba8ae7fa15..0796cf859d4ef 100644 --- a/src/dev/jest/babel_transform.js +++ b/src/dev/jest/babel_transform.js @@ -22,5 +22,5 @@ const babelJest = require('babel-jest'); module.exports = babelJest.createTransformer({ presets: [ require.resolve('@kbn/babel-preset/node_preset') - ] + ], }); diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js index 1427624f0ce98..840510815d34d 100644 --- a/src/dev/jest/config.js +++ b/src/dev/jest/config.js @@ -59,11 +59,6 @@ export default { coverageReporters: [ 'html', ], - globals: { - 'ts-jest': { - skipBabel: true, - }, - }, moduleFileExtensions: [ 'js', 'json', @@ -83,8 +78,7 @@ export default { 'integration_tests/' ], transform: { - '^.+\\.js$': '/src/dev/jest/babel_transform.js', - '^.+\\.tsx?$': '/src/dev/jest/ts_transform.js', + '^.+\\.(js|tsx?)$': '/src/dev/jest/babel_transform.js', '^.+\\.txt?$': 'jest-raw-loader', '^.+\\.html?$': 'jest-raw-loader', }, diff --git a/src/dev/jest/setup/babel_polyfill.js b/src/dev/jest/setup/babel_polyfill.js index 38e1cfbcdd721..58325c1a67f94 100644 --- a/src/dev/jest/setup/babel_polyfill.js +++ b/src/dev/jest/setup/babel_polyfill.js @@ -18,6 +18,6 @@ */ // Note: In theory importing the polyfill should not be needed, as Babel should -// include the necessary polyfills when using `babel-preset-env`, but for some +// include the necessary polyfills when using `@babel/preset-env`, but for some // reason it did not work. See https://github.com/elastic/kibana/issues/14506 import '../../../setup_node_env/babel_register/polyfill'; diff --git a/src/dev/jest/ts_transform.ts b/src/dev/jest/ts_transform.ts deleted file mode 100644 index ed366bcd091a0..0000000000000 --- a/src/dev/jest/ts_transform.ts +++ /dev/null @@ -1,74 +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 TsJest from 'ts-jest'; - -import { getTsProjectForAbsolutePath } from '../typescript'; - -const DEFAULT_TS_CONFIG_PATH = require.resolve('../../../tsconfig.json'); -const DEFAULT_BROWSER_TS_CONFIG_PATH = require.resolve('../../../tsconfig.browser.json'); - -function extendJestConfigJSON(jestConfigJSON: string, filePath: string) { - const jestConfig = JSON.parse(jestConfigJSON) as jest.ProjectConfig; - return JSON.stringify(extendJestConfig(jestConfig, filePath)); -} - -function extendJestConfig(jestConfig: jest.ProjectConfig, filePath: string) { - let tsConfigFile = getTsProjectForAbsolutePath(filePath).tsConfigPath; - - // swap ts config file for jest tests - if (tsConfigFile === DEFAULT_BROWSER_TS_CONFIG_PATH) { - tsConfigFile = DEFAULT_TS_CONFIG_PATH; - } - - return { - ...jestConfig, - globals: { - ...(jestConfig.globals || {}), - 'ts-jest': { - skipBabel: true, - tsConfigFile, - }, - }, - }; -} - -module.exports = { - canInstrument: true, - - process( - src: string, - filePath: jest.Path, - jestConfig: jest.ProjectConfig, - transformOptions: jest.TransformOptions - ) { - const extendedConfig = extendJestConfig(jestConfig, filePath); - return TsJest.process(src, filePath, extendedConfig, transformOptions); - }, - - getCacheKey( - src: string, - filePath: string, - jestConfigJSON: string, - transformOptions: jest.TransformOptions - ) { - const extendedConfigJSON = extendJestConfigJSON(jestConfigJSON, filePath); - return TsJest.getCacheKey!(src, filePath, extendedConfigJSON, transformOptions); - }, -}; diff --git a/src/dev/license_checker/config.js b/src/dev/license_checker/config.js index 9c6fa7767ee1e..879c2147ccb11 100644 --- a/src/dev/license_checker/config.js +++ b/src/dev/license_checker/config.js @@ -105,5 +105,5 @@ export const LICENSE_OVERRIDES = { 'walk@2.3.9': ['MIT'], // TODO remove this once we upgrade past or equal to v1.0.2 - 'babel-plugin-mock-imports@0.0.5': ['MIT'] + 'babel-plugin-mock-imports@1.0.1': ['MIT'] }; diff --git a/src/dev/mocha/run_mocha_cli.js b/src/dev/mocha/run_mocha_cli.js index d24f9a06eafdd..299a910127d40 100644 --- a/src/dev/mocha/run_mocha_cli.js +++ b/src/dev/mocha/run_mocha_cli.js @@ -43,7 +43,7 @@ export function runMochaCli() { // check that we aren't leaking any globals process.argv.push('--check-leaks'); // prevent globals injected from canvas plugins from triggering leak check - process.argv.push('--globals', 'core,regeneratorRuntime,_'); + process.argv.push('--globals', '__core-js_shared__,core,_, '); // ensure that mocha requires the setup_node_env script process.argv.push('--require', require.resolve('../../setup_node_env')); diff --git a/src/legacy/core_plugins/inspector_views/public/data/__snapshots__/data_view.test.js.snap b/src/legacy/core_plugins/inspector_views/public/data/__snapshots__/data_view.test.js.snap index fdd47c581b7f5..522a12b4ec84f 100644 --- a/src/legacy/core_plugins/inspector_views/public/data/__snapshots__/data_view.test.js.snap +++ b/src/legacy/core_plugins/inspector_views/public/data/__snapshots__/data_view.test.js.snap @@ -222,6 +222,8 @@ exports[`Inspector Data View component should render loading state 1`] = ` }, "_eventsCount": 1, "_maxListeners": undefined, + "tabular": undefined, + "tabularOptions": undefined, }, } } diff --git a/src/legacy/core_plugins/interpreter/common/types/register.js b/src/legacy/core_plugins/interpreter/common/types/register.js index 17b03f0229672..582843c91f83b 100644 --- a/src/legacy/core_plugins/interpreter/common/types/register.js +++ b/src/legacy/core_plugins/interpreter/common/types/register.js @@ -17,7 +17,7 @@ * under the License. */ -import 'babel-polyfill'; +import '@babel/polyfill'; import { typeSpecs } from './index'; // eslint-disable-next-line no-undef diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap index bc0bdddfdbc53..aa33eb4ab1d02 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap @@ -1125,10 +1125,7 @@ exports[`NewVisModal filter for visualization types should render as expected 1` className="euiScreenReaderOnly" > - - +

    - - +

    - + - + @@ -2595,7 +2592,7 @@ exports[`NewVisModal should render as expected 1`] = `

    - - +

    - - +

    - + - + diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts new file mode 100644 index 0000000000000..04c99a1547ba9 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts @@ -0,0 +1,26 @@ +/* + * 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 const settingsGet = jest.fn(); + +jest.doMock('ui/chrome', () => ({ + getUiSettingsClient: () => ({ + get: settingsGet, + }), +})); diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx index dd357d70f8a0a..fbb3faf7b3564 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx @@ -20,13 +20,7 @@ import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -const settingsGet = jest.fn(); - -jest.mock('ui/chrome', () => ({ - getUiSettingsClient: () => ({ - get: settingsGet, - }), -})); +import { settingsGet } from './new_vis_modal.test.mocks'; import { NewVisModal } from './new_vis_modal'; diff --git a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js index 99238fcd1c9cc..bed96987ac2b1 100644 --- a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js +++ b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js @@ -30,7 +30,7 @@ export const createTestEntryTemplate = (defaultUiSettings) => (bundle) => ` */ // import global polyfills before everything else -import 'babel-polyfill'; +import '@babel/polyfill'; import 'custom-event-polyfill'; import 'whatwg-fetch'; import 'abortcontroller-polyfill'; diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap index 8a0efdef72011..12492b0bb7b68 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap +++ b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap @@ -14,7 +14,7 @@ exports[`ScriptingHelpFlyout should render normally 1`] = ` , + "content": , "data-test-subj": "syntaxTab", "id": "syntax", "name": "Syntax", @@ -23,7 +23,7 @@ exports[`ScriptingHelpFlyout should render normally 1`] = ` tabs={ Array [ Object { - "content": , + "content": , "data-test-subj": "syntaxTab", "id": "syntax", "name": "Syntax", diff --git a/src/legacy/ui/public/query_bar/components/__snapshots__/language_switcher.test.tsx.snap b/src/legacy/ui/public/query_bar/components/__snapshots__/language_switcher.test.tsx.snap index c58cab79fdc4e..0f07889998768 100644 --- a/src/legacy/ui/public/query_bar/components/__snapshots__/language_switcher.test.tsx.snap +++ b/src/legacy/ui/public/query_bar/components/__snapshots__/language_switcher.test.tsx.snap @@ -47,9 +47,7 @@ exports[`LanguageSwitcher should toggle off if language is lucene 1`] = ` >

    { + return { + getBasePath: () => `foo`, + getUiSettingsClient: () => { + return { + get: (key: string) => { + switch (key) { + case 'history:limit': + return 10; + default: + throw new Error(`Unexpected config key: ${key}`); + } + }, + }; + }, + }; +}); + +export const mockPersistedLog = { + add: jest.fn(), + get: jest.fn(() => ['response:200']), +}; + +export const mockPersistedLogFactory = jest.fn, any>(() => { + return mockPersistedLog; +}); + +export const mockGetAutocompleteSuggestions = jest.fn(() => Promise.resolve([])); +const mockAutocompleteProvider = jest.fn(() => mockGetAutocompleteSuggestions); +export const mockGetAutocompleteProvider = jest.fn(() => mockAutocompleteProvider); + +jest.mock('ui/chrome', () => mockChromeFactory()); +jest.mock('../../chrome', () => mockChromeFactory()); +jest.mock('ui/persisted_log', () => ({ + PersistedLog: mockPersistedLogFactory, +})); +jest.mock('../../metadata', () => ({ + metadata: { + branch: 'foo', + }, +})); +jest.mock('../../autocomplete_providers', () => ({ + getAutocompleteProvider: mockGetAutocompleteProvider, +})); + +import _ from 'lodash'; +// Using doMock to avoid hoisting so that I can override only the debounce method in lodash +jest.doMock('lodash', () => ({ + ..._, + debounce: (func: () => any) => func, +})); diff --git a/src/legacy/ui/public/query_bar/components/query_bar.test.tsx b/src/legacy/ui/public/query_bar/components/query_bar.test.tsx index fdcfb77043919..f6947574bee16 100644 --- a/src/legacy/ui/public/query_bar/components/query_bar.test.tsx +++ b/src/legacy/ui/public/query_bar/components/query_bar.test.tsx @@ -17,57 +17,12 @@ * under the License. */ -const mockChromeFactory = jest.fn(() => { - return { - getBasePath: () => `foo`, - getUiSettingsClient: () => { - return { - get: (key: string) => { - switch (key) { - case 'history:limit': - return 10; - default: - throw new Error(`Unexpected config key: ${key}`); - } - }, - }; - }, - }; -}); - -const mockPersistedLog = { - add: jest.fn(), - get: jest.fn(() => ['response:200']), -}; - -const mockPersistedLogFactory = jest.fn, any>(() => { - return mockPersistedLog; -}); - -const mockGetAutocompleteSuggestions = jest.fn(() => Promise.resolve([])); -const mockAutocompleteProvider = jest.fn(() => mockGetAutocompleteSuggestions); -const mockGetAutocompleteProvider = jest.fn(() => mockAutocompleteProvider); - -jest.mock('ui/chrome', () => mockChromeFactory()); -jest.mock('../../chrome', () => mockChromeFactory()); -jest.mock('ui/persisted_log', () => ({ - PersistedLog: mockPersistedLogFactory, -})); -jest.mock('../../metadata', () => ({ - metadata: { - branch: 'foo', - }, -})); -jest.mock('../../autocomplete_providers', () => ({ - getAutocompleteProvider: mockGetAutocompleteProvider, -})); - -import _ from 'lodash'; -// Using doMock to avoid hoisting so that I can override only the debounce method in lodash -jest.doMock('lodash', () => ({ - ..._, - debounce: (func: () => any) => func, -})); +import { + mockGetAutocompleteProvider, + mockGetAutocompleteSuggestions, + mockPersistedLog, + mockPersistedLogFactory, +} from 'ui/query_bar/components/query_bar.test.mocks'; import { EuiFieldText } from '@elastic/eui'; import React from 'react'; diff --git a/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap b/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap index 6388a57832c0a..3b51c1db50d00 100644 --- a/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap +++ b/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap @@ -16,7 +16,7 @@ exports[`SuggestionsComponent Passing the index should control which suggestion onScroll={[Function]} role="listbox" > - - - - @@ -207,8 +203,7 @@ exports[`should enable saved object export option when objectId is provided 1`] aria-label="Info" content={ diff --git a/src/legacy/ui/public/utils/subscribe_with_scope.test.mocks.ts b/src/legacy/ui/public/utils/subscribe_with_scope.test.mocks.ts new file mode 100644 index 0000000000000..815d2f09150c7 --- /dev/null +++ b/src/legacy/ui/public/utils/subscribe_with_scope.test.mocks.ts @@ -0,0 +1,23 @@ +/* + * 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 const mockFatalError = jest.fn(); +jest.mock('ui/notify/fatal_error', () => ({ + fatalError: mockFatalError, +})); diff --git a/src/legacy/ui/public/utils/subscribe_with_scope.test.ts b/src/legacy/ui/public/utils/subscribe_with_scope.test.ts index a5a3312bad4bf..077875c5ac6e5 100644 --- a/src/legacy/ui/public/utils/subscribe_with_scope.test.ts +++ b/src/legacy/ui/public/utils/subscribe_with_scope.test.ts @@ -16,11 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - -const mockFatalError = jest.fn(); -jest.mock('ui/notify/fatal_error', () => ({ - fatalError: mockFatalError, -})); +import { mockFatalError } from './subscribe_with_scope.test.mocks'; import * as Rx from 'rxjs'; import { subscribeWithScope } from './subscribe_with_scope'; diff --git a/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts b/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts index 3e7623b6c25fc..ab57153755c91 100644 --- a/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts +++ b/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts @@ -20,11 +20,13 @@ import { AggParam } from '../../../agg_types'; import { AggConfig } from '../../agg_config'; -interface AggParamEditorProps { +// NOTE: we cannot export the interface with export { InterfaceName } +// as there is currently a bug on babel typescript transform plugin for it +// https://github.com/babel/babel/issues/7641 +// +export interface AggParamEditorProps { agg: AggConfig; aggParam: AggParam; value: T; setValue(value: T): void; } - -export { AggParamEditorProps }; diff --git a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts new file mode 100644 index 0000000000000..6adea30c94fb4 --- /dev/null +++ b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts @@ -0,0 +1,67 @@ +/* + * 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. + */ + +jest.useFakeTimers(); + +import { EventEmitter } from 'events'; + +jest.mock('ui/notify', () => ({ + toastNotifications: jest.fn(), +})); + +jest.mock('./utils', () => ({ + queryGeohashBounds: jest.fn(), +})); + +jest.mock('./pipeline_helpers/utilities', () => ({ + getFormat: jest.fn(), + getTableAggs: jest.fn(), +})); + +export const timefilter = new EventEmitter(); +jest.doMock('../../timefilter', () => ({ timefilter })); + +jest.mock('../../inspector', () => ({ + Inspector: { + open: jest.fn(), + isAvailable: jest.fn(), + }, +})); + +export const mockDataLoaderFetch = jest.fn().mockReturnValue({ + as: 'visualization', + value: { + visType: 'histogram', + visData: {}, + visConfig: {}, + params: {}, + }, +}); +const MockDataLoader = class { + public async fetch(data: any) { + return await mockDataLoaderFetch(data); + } +}; + +jest.mock('./pipeline_data_loader', () => ({ + PipelineDataLoader: MockDataLoader, +})); +jest.mock('./visualize_data_loader', () => ({ + VisualizeDataLoader: MockDataLoader, +})); diff --git a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts index 3dc39ba7e2a90..e5a4eb122dc88 100644 --- a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts +++ b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts @@ -16,61 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - -jest.useFakeTimers(); - -import { EventEmitter } from 'events'; +import { mockDataLoaderFetch, timefilter } from './embedded_visualize_handler.test.mocks'; // @ts-ignore import MockState from '../../../../../fixtures/mock_state'; import { RequestHandlerParams, Vis } from '../../vis'; import { VisResponseData } from './types'; -jest.mock('ui/notify', () => ({ - toastNotifications: jest.fn(), -})); - -jest.mock('./utils', () => ({ - queryGeohashBounds: jest.fn(), -})); - -jest.mock('./pipeline_helpers/utilities', () => ({ - getFormat: jest.fn(), - getTableAggs: jest.fn(), -})); - -const timefilter = new EventEmitter(); -jest.mock('../../timefilter', () => ({ timefilter })); - -jest.mock('../../inspector', () => ({ - Inspector: { - open: jest.fn(), - isAvailable: jest.fn(), - }, -})); - -const mockDataLoaderFetch = jest.fn().mockReturnValue({ - as: 'visualization', - value: { - visType: 'histogram', - visData: {}, - visConfig: {}, - params: {}, - }, -}); -const MockDataLoader = class { - public async fetch(data: any) { - return await mockDataLoaderFetch(data); - } -}; - -jest.mock('./pipeline_data_loader', () => ({ - PipelineDataLoader: MockDataLoader, -})); -jest.mock('./visualize_data_loader', () => ({ - VisualizeDataLoader: MockDataLoader, -})); - import { Inspector } from '../../inspector'; import { EmbeddedVisualizeHandler } from './embedded_visualize_handler'; diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts index fe9a36a0e5a63..3617c77e42b0f 100644 --- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts +++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts @@ -31,7 +31,7 @@ import { fieldFormats } from '../../../registry/field_formats'; const config = chrome.getUiSettingsClient(); const defaultFormat = { convert: identity }; -const getConfig = (...args: any[]): any => (config.get as any)(...args); +const getConfig = (...args: any[]): any => config.get(...args); const getFieldFormat = (id: string, params: object) => { const Format = fieldFormats.byId[id]; diff --git a/src/legacy/ui/ui_bundles/app_entry_template.js b/src/legacy/ui/ui_bundles/app_entry_template.js index 2d92dc30556fb..625ce5e381d21 100644 --- a/src/legacy/ui/ui_bundles/app_entry_template.js +++ b/src/legacy/ui/ui_bundles/app_entry_template.js @@ -33,7 +33,7 @@ import 'dll/set_csp_nonce'; __webpack_nonce__ = window.__kbnNonce__; // import global polyfills -import 'babel-polyfill'; +import '@babel/polyfill'; import 'custom-event-polyfill'; import 'whatwg-fetch'; import 'abortcontroller-polyfill'; diff --git a/src/optimize/base_optimizer.js b/src/optimize/base_optimizer.js index b260f57df3311..bb130e3869509 100644 --- a/src/optimize/base_optimizer.js +++ b/src/optimize/base_optimizer.js @@ -123,10 +123,6 @@ export default class BaseOptimizer { BABEL_PRESET_PATH ]; - const nonDistributableOnlyModules = !IS_KIBANA_DISTRIBUTABLE - ? ['ts-loader'] - : []; - threadLoader.warmup( // pool options, like passed to loader options // must match loader options to boot the correct pool @@ -134,7 +130,6 @@ export default class BaseOptimizer { [ // modules to load on the pool ...baseModules, - ...nonDistributableOnlyModules ] ); } @@ -368,7 +363,7 @@ export default class BaseOptimizer { } }, { - resource: createSourceFileResourceSelector(/\.js$/), + resource: createSourceFileResourceSelector(/\.(js|tsx?)$/), use: maybeAddCacheLoader('babel', [ { loader: 'thread-loader', @@ -394,7 +389,7 @@ export default class BaseOptimizer { }, resolve: { - extensions: ['.js', '.json'], + extensions: ['.js', '.ts', '.tsx', '.json'], mainFields: ['browser', 'browserify', 'main'], modules: [ 'webpackShims', @@ -429,47 +424,6 @@ export default class BaseOptimizer { ] }; - // when running from source transpile TypeScript automatically - const getSourceConfig = () => { - // dev/typescript is deleted from the distributable, so only require it if we actually need the source config - const { Project } = require('../dev/typescript'); - const browserProject = new Project(fromRoot('tsconfig.browser.json')); - - return { - module: { - rules: [ - { - resource: createSourceFileResourceSelector(/\.tsx?$/), - use: maybeAddCacheLoader('typescript', [ - { - loader: 'thread-loader', - options: this.getThreadLoaderPoolConfig() - }, - { - loader: 'ts-loader', - options: { - happyPackMode: true, - transpileOnly: true, - experimentalWatchApi: true, - onlyCompileBundledFiles: true, - configFile: fromRoot('tsconfig.json'), - compilerOptions: { - ...browserProject.config.compilerOptions, - sourceMap: Boolean(this.sourceMaps), - } - } - } - ]), - } - ] - }, - - resolve: { - extensions: ['.ts', '.tsx'], - }, - }; - }; - // We need to add react-addons (and a few other bits) for enzyme to work. // https://github.com/airbnb/enzyme/blob/master/docs/guides/webpack.md const supportEnzymeConfig = { @@ -516,7 +470,7 @@ export default class BaseOptimizer { commonConfig, IS_KIBANA_DISTRIBUTABLE ? isDistributableConfig - : getSourceConfig(), + : {}, this.uiBundles.isDevMode() ? webpackMerge(watchingConfig, supportEnzymeConfig) : productionConfig diff --git a/src/optimize/watch/watch_cache.ts b/src/optimize/watch/watch_cache.ts index 01afed1b2640f..ab11a8c5d2f11 100644 --- a/src/optimize/watch/watch_cache.ts +++ b/src/optimize/watch/watch_cache.ts @@ -95,16 +95,7 @@ export class WatchCache { await del(this.statePath, { force: true }); // delete everything in optimize/.cache directory - // except ts-node - await del( - await globby( - [ - normalizePosixPath(this.cachePath), - `${normalizePosixPath(`!${this.cachePath}/ts-node/**`)}`, - ], - { dot: true } - ) - ); + await del(await globby([normalizePosixPath(this.cachePath)], { dot: true })); // delete some empty folder that could be left // from the previous cache path reset action diff --git a/src/setup_node_env/babel_register/index.js b/src/setup_node_env/babel_register/index.js index 44b9427ed8e3e..1574be8937a29 100644 --- a/src/setup_node_env/babel_register/index.js +++ b/src/setup_node_env/babel_register/index.js @@ -17,16 +17,6 @@ * under the License. */ -// unless we are running a prebuilt/distributable version of -// kibana, automatically transpile typescript to js before babel -if (!global.__BUILT_WITH_BABEL__) { - var resolve = require('path').resolve; - require('ts-node').register({ - transpileOnly: true, - cacheDirectory: resolve(__dirname, '../../../optimize/.cache/ts-node') - }); -} - // register and polyfill need to happen in this // order and in separate files. Checkout each file // for a much more detailed explanation diff --git a/src/setup_node_env/babel_register/polyfill.js b/src/setup_node_env/babel_register/polyfill.js index e72a2eff001ad..4e92583f830e5 100644 --- a/src/setup_node_env/babel_register/polyfill.js +++ b/src/setup_node_env/babel_register/polyfill.js @@ -17,13 +17,13 @@ * under the License. */ -// `babel-preset-env` looks for and rewrites the following import +// `@babel/preset-env` looks for and rewrites the following import // statement into a list of import statements based on the polyfills // necessary for our target environment (the current version of node) -// but since it does that during compilation, `import 'babel-polyfill'` -// must be in a file that is loaded with `require()` AFTER `babel-register` +// but since it does that during compilation, `import '@babel/polyfill'` +// must be in a file that is loaded with `require()` AFTER `@babel/register` // is configured. // // This is why we have this single statement in it's own file and require // it from ./index.js -require('babel-polyfill'); +require('@babel/polyfill'); diff --git a/src/setup_node_env/babel_register/register.js b/src/setup_node_env/babel_register/register.js index f0898b245fb0e..37e39d4685cac 100644 --- a/src/setup_node_env/babel_register/register.js +++ b/src/setup_node_env/babel_register/register.js @@ -19,13 +19,13 @@ var resolve = require('path').resolve; -// this must happen before `require('babel-register')` and can't be changed +// this must happen before `require('@babel/register')` and can't be changed // once the module has been loaded if (!process.env.BABEL_CACHE_PATH) { process.env.BABEL_CACHE_PATH = resolve(__dirname, '../../../optimize/.babelcache.json'); } -// paths that babel-register should ignore +// paths that @babel/register should ignore var ignore = [ /\/bower_components\//, /\/kbn-pm\/dist\//, @@ -48,10 +48,10 @@ var ignore = [ if (global.__BUILT_WITH_BABEL__) { // when building the Kibana source we replace the statement // `global.__BUILT_WITH_BABEL__` with the value `true` so that - // when babel-register is required for the first time by users + // when @babel/register is required for the first time by users // it will exclude kibana's `src` directory. // - // We still need babel-register for plugins though, we've been + // We still need @babel/register for plugins though, we've been // building their server code at require-time since version 4.2 // TODO: the plugin install process could transpile plugin server code... ignore.push(resolve(__dirname, '../../../src')); @@ -66,10 +66,11 @@ if (global.__BUILT_WITH_BABEL__) { // modifies all future calls to require() to automatically // compile the required source with babel -require('babel-register')({ +require('@babel/register')({ ignore, babelrc: false, presets: [ require.resolve('@kbn/babel-preset/node_preset') ], + extensions: ['.js', '.ts', '.tsx'], }); diff --git a/x-pack/dev-tools/jest/create_jest_config.js b/x-pack/dev-tools/jest/create_jest_config.js index bf20e88333787..ad5b2fde1acfe 100644 --- a/x-pack/dev-tools/jest/create_jest_config.js +++ b/x-pack/dev-tools/jest/create_jest_config.js @@ -37,8 +37,7 @@ export function createJestConfig({ '**/*.test.{js,ts,tsx}' ], transform: { - '^.+\\.js$': `${kibanaDirectory}/src/dev/jest/babel_transform.js`, - '^.+\\.tsx?$': `${kibanaDirectory}/src/dev/jest/ts_transform.js`, + '^.+\\.(js|tsx?)$': `${kibanaDirectory}/src/dev/jest/babel_transform.js`, }, transformIgnorePatterns: [ '[/\\\\]node_modules[/\\\\].+\\.js$' diff --git a/x-pack/package.json b/x-pack/package.json index 2ad347a2d7284..7655ffdefdcc5 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -74,11 +74,11 @@ "ansi-colors": "^3.0.5", "ansicolors": "0.3.2", "axios": "^0.18.0", - "babel-jest": "^23.6.0", - "babel-plugin-inline-react-svg": "^0.5.4", - "babel-plugin-mock-imports": "^0.0.5", - "babel-plugin-require-context-hook": "^1.0.0", - "babel-plugin-transform-react-remove-prop-types": "^0.4.14", + "babel-jest": "^24.1.0", + "babel-plugin-inline-react-svg": "^1.0.1", + "babel-plugin-mock-imports": "^1.0.1", + "babel-plugin-require-context-hook": "npm:babel-plugin-require-context-hook-babel7@^1.0.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "chalk": "^2.4.1", "chance": "1.0.10", "checksum": "0.1.1", @@ -128,13 +128,16 @@ "supertest-as-promised": "^4.0.2", "tmp": "0.0.31", "tree-kill": "^1.1.0", - "ts-loader": "^5.2.2", "typescript": "^3.3.3333", "vinyl-fs": "^3.0.2", "xml-crypto": "^0.10.1", "yargs": "4.8.1" }, "dependencies": { + "@babel/core": "^7.3.4", + "@babel/polyfill": "^7.2.5", + "@babel/register": "^7.0.0", + "@babel/runtime": "^7.3.4", "@elastic/datemath": "5.0.2", "@elastic/eui": "9.5.0", "@elastic/node-crypto": "0.1.2", @@ -160,11 +163,6 @@ "apollo-server-errors": "^2.0.2", "apollo-server-hapi": "^1.3.6", "axios": "^0.18.0", - "babel-core": "^6.26.3", - "babel-polyfill": "6.20.0", - "babel-preset-es2015": "^6.24.1", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", "base64-js": "^1.2.1", "bluebird": "3.5.3", "boom": "^7.2.0", diff --git a/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverLinks.integration.test.tsx b/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverLinks.integration.test.tsx index ed5c609cb9003..12198b1a870df 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverLinks.integration.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverLinks.integration.test.tsx @@ -15,8 +15,6 @@ import { DiscoverErrorLink } from '../DiscoverErrorLink'; import { DiscoverSpanLink } from '../DiscoverSpanLink'; import { DiscoverTransactionLink } from '../DiscoverTransactionLink'; -// NOTE: jest.mock() is broken in TS test files (b/c of ts-jest, I think) -// but using jest's "spies can be stubbed" feature, this works: jest .spyOn(savedObjects, 'getAPMIndexPattern') .mockReturnValue( diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx b/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx index 47cffde62612e..61d2fcf026652 100644 --- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx @@ -4,18 +4,33 @@ * you may not use this file except in compliance with the Elastic License. */ +jest.mock('../tabConfigConst', () => { + return { + TAB_CONFIG: [ + { + key: 'testProperty', + label: 'testPropertyLabel', + required: false, + presortedKeys: ['name', 'age'] + }, + { + key: 'optionalProperty', + label: 'optionalPropertyLabel', + required: false + }, + { + key: 'requiredProperty', + label: 'requiredPropertyLabel', + required: true + } + ] + }; +}); + import * as propertyConfig from '../tabConfig'; const { getTabsFromObject, sortKeysByConfig } = propertyConfig; describe('tabConfig', () => { - beforeEach(() => { - mockPropertyConfig(); - }); - - afterEach(() => { - unMockPropertyConfig(); - }); - describe('getTabsFromObject', () => { it('should return selected and required keys only', () => { const expectedTabs = [ @@ -64,31 +79,3 @@ describe('tabConfig', () => { }); }); }); - -function mockPropertyConfig() { - // @ts-ignore - propertyConfig.TAB_CONFIG = [ - { - key: 'testProperty', - label: 'testPropertyLabel', - required: false, - presortedKeys: ['name', 'age'] - }, - { - key: 'optionalProperty', - label: 'optionalPropertyLabel', - required: false - }, - { - key: 'requiredProperty', - label: 'requiredPropertyLabel', - required: true - } - ]; -} - -const originalPropertyConfig = propertyConfig.TAB_CONFIG; -function unMockPropertyConfig() { - // @ts-ignore - propertyConfig.TAB_CONFIG = originalPropertyConfig; -} diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts index cb9ce7f8538bc..2648c2875cd84 100644 --- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts +++ b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts @@ -4,28 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; import { get, indexBy, uniq } from 'lodash'; import { first, has } from 'lodash'; import { StringMap } from 'x-pack/plugins/apm/typings/common'; import { APMError } from 'x-pack/plugins/apm/typings/es_schemas/ui/APMError'; import { Transaction } from 'x-pack/plugins/apm/typings/es_schemas/ui/Transaction'; - -export type PropertyTabKey = - | keyof Transaction - | keyof APMError - | 'transaction.custom' - | 'error.custom'; - -export interface PropertyTab { - key: PropertyTabKey; - label: string; -} - -interface TabConfig extends PropertyTab { - required: boolean; - presortedKeys: string[]; -} +import { + PropertyTab, + PropertyTabKey, + TAB_CONFIG, + TabConfig +} from './tabConfigConst'; export function getTabsFromObject(obj: Transaction | APMError): PropertyTab[] { return TAB_CONFIG.filter( @@ -53,96 +42,4 @@ export function getCurrentTab( return selectedTab ? selectedTab : first(tabs) || {}; } -export const TAB_CONFIG: TabConfig[] = [ - { - key: 'http', - label: i18n.translate('xpack.apm.propertiesTable.tabs.httpLabel', { - defaultMessage: 'HTTP' - }), - required: false, - presortedKeys: [] - }, - { - key: 'host', - label: i18n.translate('xpack.apm.propertiesTable.tabs.hostLabel', { - defaultMessage: 'Host' - }), - required: false, - presortedKeys: ['hostname', 'architecture', 'platform'] - }, - { - key: 'service', - label: i18n.translate('xpack.apm.propertiesTable.tabs.serviceLabel', { - defaultMessage: 'Service' - }), - required: false, - presortedKeys: ['runtime', 'framework', 'version'] - }, - { - key: 'process', - label: i18n.translate('xpack.apm.propertiesTable.tabs.processLabel', { - defaultMessage: 'Process' - }), - required: false, - presortedKeys: ['pid', 'title', 'args'] - }, - { - key: 'agent', - label: i18n.translate('xpack.apm.propertiesTable.tabs.agentLabel', { - defaultMessage: 'Agent' - }), - required: false, - presortedKeys: [] - }, - { - key: 'url', - label: i18n.translate('xpack.apm.propertiesTable.tabs.urlLabel', { - defaultMessage: 'URL' - }), - required: false, - presortedKeys: [] - }, - { - key: 'container', - label: i18n.translate('xpack.apm.propertiesTable.tabs.containerLabel', { - defaultMessage: 'Container' - }), - required: false, - presortedKeys: [] - }, - { - key: 'user', - label: i18n.translate('xpack.apm.propertiesTable.tabs.userLabel', { - defaultMessage: 'User' - }), - required: true, - presortedKeys: ['id', 'username', 'email'] - }, - { - key: 'labels', - label: i18n.translate('xpack.apm.propertiesTable.tabs.labelsLabel', { - defaultMessage: 'Labels' - }), - required: true, - presortedKeys: [] - }, - { - key: 'transaction.custom', - label: i18n.translate( - 'xpack.apm.propertiesTable.tabs.transactionCustomLabel', - { - defaultMessage: 'Custom' - } - ), - required: false, - presortedKeys: [] - }, - { - key: 'error.custom', - label: i18n.translate('xpack.apm.propertiesTable.tabs.errorCustomLabel', { - defaultMessage: 'Custom' - }), - required: false, - presortedKeys: [] - } -]; +export { TAB_CONFIG, TabConfig, PropertyTab, PropertyTabKey }; diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts new file mode 100644 index 0000000000000..95c4f6da9f37e --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts @@ -0,0 +1,119 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { APMError } from 'x-pack/plugins/apm/typings/es_schemas/ui/APMError'; +import { Transaction } from 'x-pack/plugins/apm/typings/es_schemas/ui/Transaction'; + +export type PropertyTabKey = + | keyof Transaction + | keyof APMError + | 'transaction.custom' + | 'error.custom'; + +export interface PropertyTab { + key: PropertyTabKey; + label: string; +} + +export interface TabConfig extends PropertyTab { + required: boolean; + presortedKeys: string[]; +} + +export const TAB_CONFIG: TabConfig[] = [ + { + key: 'http', + label: i18n.translate('xpack.apm.propertiesTable.tabs.httpLabel', { + defaultMessage: 'HTTP' + }), + required: false, + presortedKeys: [] + }, + { + key: 'host', + label: i18n.translate('xpack.apm.propertiesTable.tabs.hostLabel', { + defaultMessage: 'Host' + }), + required: false, + presortedKeys: ['hostname', 'architecture', 'platform'] + }, + { + key: 'service', + label: i18n.translate('xpack.apm.propertiesTable.tabs.serviceLabel', { + defaultMessage: 'Service' + }), + required: false, + presortedKeys: ['runtime', 'framework', 'version'] + }, + { + key: 'process', + label: i18n.translate('xpack.apm.propertiesTable.tabs.processLabel', { + defaultMessage: 'Process' + }), + required: false, + presortedKeys: ['pid', 'title', 'args'] + }, + { + key: 'agent', + label: i18n.translate('xpack.apm.propertiesTable.tabs.agentLabel', { + defaultMessage: 'Agent' + }), + required: false, + presortedKeys: [] + }, + { + key: 'url', + label: i18n.translate('xpack.apm.propertiesTable.tabs.urlLabel', { + defaultMessage: 'URL' + }), + required: false, + presortedKeys: [] + }, + { + key: 'container', + label: i18n.translate('xpack.apm.propertiesTable.tabs.containerLabel', { + defaultMessage: 'Container' + }), + required: false, + presortedKeys: [] + }, + { + key: 'user', + label: i18n.translate('xpack.apm.propertiesTable.tabs.userLabel', { + defaultMessage: 'User' + }), + required: true, + presortedKeys: ['id', 'username', 'email'] + }, + { + key: 'labels', + label: i18n.translate('xpack.apm.propertiesTable.tabs.labelsLabel', { + defaultMessage: 'Labels' + }), + required: true, + presortedKeys: [] + }, + { + key: 'transaction.custom', + label: i18n.translate( + 'xpack.apm.propertiesTable.tabs.transactionCustomLabel', + { + defaultMessage: 'Custom' + } + ), + required: false, + presortedKeys: [] + }, + { + key: 'error.custom', + label: i18n.translate('xpack.apm.propertiesTable.tabs.errorCustomLabel', { + defaultMessage: 'Custom' + }), + required: false, + presortedKeys: [] + } +]; diff --git a/x-pack/plugins/canvas/.storybook/webpack.config.js b/x-pack/plugins/canvas/.storybook/webpack.config.js index b52a4020c5923..39e33c9613e44 100644 --- a/x-pack/plugins/canvas/.storybook/webpack.config.js +++ b/x-pack/plugins/canvas/.storybook/webpack.config.js @@ -17,7 +17,7 @@ module.exports = (_baseConfig, _env, config) => { include: /\.storybook/, loaders: 'babel-loader', options: { - presets: [require.resolve('babel-preset-react')], + presets: [require.resolve('@babel/preset-react')], }, }, ); diff --git a/x-pack/plugins/canvas/public/components/workpad_page/index.js b/x-pack/plugins/canvas/public/components/workpad_page/index.js index adc6bae7418a9..7a408de335831 100644 --- a/x-pack/plugins/canvas/public/components/workpad_page/index.js +++ b/x-pack/plugins/canvas/public/components/workpad_page/index.js @@ -41,6 +41,7 @@ const mapDispatchToProps = dispatch => { }; }; +// eslint-disable-next-line const getRootElementId = (lookup, id) => { if (!lookup.has(id)) { return null; diff --git a/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js b/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js index 6e93f9eb5fb4b..d62fbe21fa0f0 100644 --- a/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js +++ b/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js @@ -436,6 +436,7 @@ export const applyLocalTransforms = (shapes, transformIntents) => { return shapes.map(shapeApplyLocalTransforms(transformIntents)); }; +// eslint-disable-next-line const getUpstreamTransforms = (shapes, shape) => shape.parent ? getUpstreamTransforms(shapes, shapes.find(s => s.id === shape.parent)).concat([ diff --git a/x-pack/plugins/canvas/tasks/helpers/babelhook.js b/x-pack/plugins/canvas/tasks/helpers/babelhook.js index 4a48d09449b20..dea18db918fcd 100644 --- a/x-pack/plugins/canvas/tasks/helpers/babelhook.js +++ b/x-pack/plugins/canvas/tasks/helpers/babelhook.js @@ -5,7 +5,7 @@ */ const { resolve } = require('path'); -const register = require('babel-register'); +const register = require('@babel/register'); const options = { babelrc: false, presets: [require.resolve('@kbn/babel-preset/node_preset')], diff --git a/x-pack/plugins/infra/scripts/generate_types_from_graphql.js b/x-pack/plugins/infra/scripts/generate_types_from_graphql.js index 091e692d0bbd4..caeb73c3bf797 100644 --- a/x-pack/plugins/infra/scripts/generate_types_from_graphql.js +++ b/x-pack/plugins/infra/scripts/generate_types_from_graphql.js @@ -28,7 +28,6 @@ async function main() { config: SERVER_CONFIG_PATH, out: OUTPUT_INTROSPECTION_PATH, overwrite: true, - require: ['ts-node/register'], schema: SCHEMA_PATH, template: 'graphql-codegen-introspection-template', }, diff --git a/x-pack/plugins/ml/public/components/form_label/__snapshots__/form_label.test.js.snap b/x-pack/plugins/ml/public/components/form_label/__snapshots__/form_label.test.js.snap index 8b7d26d3c7551..327a8dc4fee4e 100644 --- a/x-pack/plugins/ml/public/components/form_label/__snapshots__/form_label.test.js.snap +++ b/x-pack/plugins/ml/public/components/form_label/__snapshots__/form_label.test.js.snap @@ -6,7 +6,7 @@ exports[`FormLabel Basic initialization 1`] = ` className="euiFormLabel" id="ml_aria_label_undefined" /> - @@ -20,7 +20,7 @@ exports[`FormLabel Full initialization 1`] = ` > Label Text - diff --git a/x-pack/plugins/ml/public/components/kql_filter_bar/suggestions/__snapshots__/suggestions.test.js.snap b/x-pack/plugins/ml/public/components/kql_filter_bar/suggestions/__snapshots__/suggestions.test.js.snap index 7133002e495c1..869e321d4a7af 100644 --- a/x-pack/plugins/ml/public/components/kql_filter_bar/suggestions/__snapshots__/suggestions.test.js.snap +++ b/x-pack/plugins/ml/public/components/kql_filter_bar/suggestions/__snapshots__/suggestions.test.js.snap @@ -4,7 +4,7 @@ exports[`Suggestions snapshot 1`] = ` - - - + - + diff --git a/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap index d6db223edc136..2ab3c6b3aa7b4 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap @@ -286,7 +286,7 @@ exports[`ExplainCollectionInterval collection interval setting updates should sh isCollectionIntervalUpdating={true} property="xpack.monitoring.collection.interval" > - + - + @@ -609,7 +609,7 @@ exports[`ExplainCollectionInterval should explain about xpack.monitoring.collect isCollectionIntervalUpdating={false} property="xpack.monitoring.collection.interval" > - + - + diff --git a/x-pack/plugins/reporting/public/components/report_info_button.test.mocks.ts b/x-pack/plugins/reporting/public/components/report_info_button.test.mocks.ts new file mode 100644 index 0000000000000..7f1392cb2a49a --- /dev/null +++ b/x-pack/plugins/reporting/public/components/report_info_button.test.mocks.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export const mockJobQueueClient = { getInfo: jest.fn() }; +jest.mock('../lib/job_queue_client', () => ({ jobQueueClient: mockJobQueueClient })); diff --git a/x-pack/plugins/reporting/public/components/report_info_button.test.tsx b/x-pack/plugins/reporting/public/components/report_info_button.test.tsx index 93ceed0f64a0e..3b9c2a8485423 100644 --- a/x-pack/plugins/reporting/public/components/report_info_button.test.tsx +++ b/x-pack/plugins/reporting/public/components/report_info_button.test.tsx @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -const mockJobQueueClient = { getInfo: jest.fn() }; -jest.mock('../lib/job_queue_client', () => ({ jobQueueClient: mockJobQueueClient })); +import { mockJobQueueClient } from './report_info_button.test.mocks'; import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; diff --git a/x-pack/plugins/reporting/public/components/report_listing.tsx b/x-pack/plugins/reporting/public/components/report_listing.tsx index 262362a1e5a51..56f0e382d23a6 100644 --- a/x-pack/plugins/reporting/public/components/report_listing.tsx +++ b/x-pack/plugins/reporting/public/components/report_listing.tsx @@ -23,7 +23,7 @@ import { ReportErrorButton } from './report_error_button'; import { ReportInfoButton } from './report_info_button'; import { - EuiBasicTable, + EuiBasicTable as EuiBasicTableTyped, EuiButtonIcon, EuiPageContent, EuiSpacer, @@ -296,7 +296,7 @@ class ReportListingUi extends Component { }; return ( - ; } -import { EuiButton, EuiCopy, EuiForm, EuiFormRow, EuiSpacer, EuiText } from '@elastic/eui'; +import { + EuiButton, + EuiCopy as EuiCopyTyped, + EuiForm, + EuiFormRow, + EuiSpacer, + EuiText, +} from '@elastic/eui'; import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import React, { Component, ReactElement } from 'react'; import { KFetchError } from 'ui/kfetch/kfetch_error'; @@ -131,7 +138,7 @@ class ReportingPanelContentUi extends Component { - @@ -143,7 +150,7 @@ class ReportingPanelContentUi extends Component { /> )} - + ); } diff --git a/x-pack/plugins/searchprofiler/README.md b/x-pack/plugins/searchprofiler/README.md index 54bbd1203235d..1dec1bb4e5450 100644 --- a/x-pack/plugins/searchprofiler/README.md +++ b/x-pack/plugins/searchprofiler/README.md @@ -19,7 +19,7 @@ If you have installed this somewhere other than via x-plugins, and next to the k To run the server tests, change into `x-plugins/kibana` and run: ```bash -mocha --debug --compilers js:babel/register plugins/profiler/**/__tests__/**/*.js +mocha --debug --compilers js:@babel/register plugins/profiler/**/__tests__/**/*.js ``` diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/privilege_callout_warning.test.tsx.snap b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/privilege_callout_warning.test.tsx.snap index 5c38e3f28c4d0..19dacf984f5dc 100644 --- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/privilege_callout_warning.test.tsx.snap +++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/privilege_callout_warning.test.tsx.snap @@ -179,9 +179,7 @@ exports[`PrivilegeCalloutWarning renders without crashing 1`] = ` >

    - grants full access to all - spaces. To customize privileges for individual spaces, the minimum privilege must be - either + grants full access to all spaces. To customize privileges for individual spaces, the minimum privilege must be either renders without crashing 1`] = ` >

    with user profile disabling "manageSpaces" re

    { const subject = buildPrivilegeMap; it('should produce an object of the expected form', () => { - const getSavedObjectAction = sinon.fake((t: any, a: any) => { + const getSavedObjectAction = sinon.fake((t, a) => { if (!t || !isString(t)) { throw new Error('type is required and must be a string'); } diff --git a/x-pack/plugins/spaces/public/components/__snapshots__/space_avatar.test.tsx.snap b/x-pack/plugins/spaces/public/components/__snapshots__/space_avatar.test.tsx.snap index da0f3ed3558e2..9b6336ad64447 100644 --- a/x-pack/plugins/spaces/public/components/__snapshots__/space_avatar.test.tsx.snap +++ b/x-pack/plugins/spaces/public/components/__snapshots__/space_avatar.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`removes aria-label when instructed not to announce the space name 1`] = ` - - + `; exports[`renders with a space name entirely made of whitespace 1`] = ` diff --git a/x-pack/plugins/spaces/public/views/management/components/advanced_settings_title/__snapshots__/advanced_settings_title.test.tsx.snap b/x-pack/plugins/spaces/public/views/management/components/advanced_settings_title/__snapshots__/advanced_settings_title.test.tsx.snap index 42da3769ac8e0..5b3b0cede89a0 100644 --- a/x-pack/plugins/spaces/public/views/management/components/advanced_settings_title/__snapshots__/advanced_settings_title.test.tsx.snap +++ b/x-pack/plugins/spaces/public/views/management/components/advanced_settings_title/__snapshots__/advanced_settings_title.test.tsx.snap @@ -9,7 +9,7 @@ exports[`AdvancedSettingsTitle renders as expected 1`] = ` - - - , - , + - , - , + - , + , ] `; diff --git a/x-pack/plugins/spaces/public/views/nav_control/__snapshots__/nav_control_popover.test.tsx.snap b/x-pack/plugins/spaces/public/views/nav_control/__snapshots__/nav_control_popover.test.tsx.snap index 00c49341ce0e7..265dcc349e1b9 100644 --- a/x-pack/plugins/spaces/public/views/nav_control/__snapshots__/nav_control_popover.test.tsx.snap +++ b/x-pack/plugins/spaces/public/views/nav_control/__snapshots__/nav_control_popover.test.tsx.snap @@ -6,7 +6,7 @@ exports[`NavControlPopover renders without crashing 1`] = ` button={ - - - diff --git a/x-pack/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap index 3a726b70fc9e4..170d668a027ac 100644 --- a/x-pack/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap @@ -17,16 +17,14 @@ exports[`ChecklistFlyout renders 1`] = ` >

    @@ -45,7 +43,7 @@ exports[`ChecklistFlyout renders 1`] = ` />

    - { ); expect(wrapper).toMatchInlineSnapshot(` - { ); expect(wrapper).toMatchInlineSnapshot(` - ({ + create: jest.fn().mockReturnValue(mockClient), +})); diff --git a/x-pack/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts b/x-pack/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts index f15927c0d6a3b..9f47f51bc8cde 100644 --- a/x-pack/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/public/components/tabs/checkup/deprecations/reindex/polling_service.test.ts @@ -4,25 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ReindexStatus, ReindexStep } from '../../../../../../common/types'; - -const mockClient = { - post: jest.fn().mockResolvedValue({ - lastCompletedStep: ReindexStep.created, - status: ReindexStatus.inProgress, - }), - get: jest.fn().mockResolvedValue({ - status: 200, - data: { - warnings: [], - reindexOp: null, - }, - }), -}; -jest.mock('axios', () => ({ - create: jest.fn().mockReturnValue(mockClient), -})); +import { mockClient } from './polling_service.test.mocks'; +import { ReindexStatus, ReindexStep } from '../../../../../../common/types'; import { ReindexPollingService } from './polling_service'; describe('ReindexPollingService', () => { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts index 9d37fec650b70..1b19db8a378ef 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts @@ -7,7 +7,7 @@ import { CallCluster, CallClusterWithRequest } from 'src/legacy/core_plugins/ela import { Request, Server } from 'src/legacy/server/kbn_server'; import { SavedObjectsClient } from 'src/legacy/server/saved_objects'; -import moment = require('moment'); +import moment from 'moment'; import { XPackInfo } from 'x-pack/plugins/xpack_main/server/lib/xpack_info'; import { ReindexSavedObject, ReindexStatus } from '../../../common/types'; import { CredentialStore } from './credential_store'; diff --git a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot.test.tsx.snap b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot.test.tsx.snap index 717cb187623a7..030b03f1c75ac 100644 --- a/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot.test.tsx.snap @@ -111,7 +111,7 @@ exports[`Snapshot component renders without errors 1`] = ` } } > - - - - + + `; exports[`EmptyState component renders child components when count is truthy 1`] = ` @@ -268,7 +268,7 @@ exports[`EmptyState component renders child components when count is truthy 1`] `; exports[`EmptyState component renders empty state with appropriate base path 1`] = ` - - - - + + `; exports[`EmptyState component renders message while loading 1`] = ` - - + - - + + `; exports[`EmptyState component renders the message when an error occurs 1`] = ` - - - - + + `; diff --git a/x-pack/plugins/uptime/scripts/infer_graphql_types.js b/x-pack/plugins/uptime/scripts/infer_graphql_types.js index c4b87c9ea9339..104fd5b66b5d6 100644 --- a/x-pack/plugins/uptime/scripts/infer_graphql_types.js +++ b/x-pack/plugins/uptime/scripts/infer_graphql_types.js @@ -20,7 +20,6 @@ async function main() { config: CONFIG_PATH, out: OUTPUT_INTROSPECTION_PATH, overwrite: true, - require: ['ts-node/register'], schema: SCHEMA_PATH, template: 'graphql-codegen-introspection-template', }, diff --git a/x-pack/plugins/xpack_main/server/lib/file_integrity.test.mocks.ts b/x-pack/plugins/xpack_main/server/lib/file_integrity.test.mocks.ts new file mode 100644 index 0000000000000..36f76516e188b --- /dev/null +++ b/x-pack/plugins/xpack_main/server/lib/file_integrity.test.mocks.ts @@ -0,0 +1,28 @@ +/* + * 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 { Readable } from 'stream'; + +jest.doMock('fs', () => ({ + createReadStream(filepath: string): Readable { + if (filepath === 'ERROR') { + throw new Error('MOCK ERROR - Invalid Path'); + } + const readableStream = new Readable(); + const streamData = filepath.split(''); + let cursor = 0; + + readableStream._read = function(size) { + const current = streamData[cursor++]; + if (typeof current === 'undefined') { + return this.push(null); + } + this.push(current); + }; + + return readableStream; + }, +})); diff --git a/x-pack/plugins/xpack_main/server/lib/file_integrity.test.ts b/x-pack/plugins/xpack_main/server/lib/file_integrity.test.ts index 5e554cd77d849..668b0d0c21088 100644 --- a/x-pack/plugins/xpack_main/server/lib/file_integrity.test.ts +++ b/x-pack/plugins/xpack_main/server/lib/file_integrity.test.ts @@ -4,28 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Readable } from 'stream'; - -jest.mock('fs', () => ({ - createReadStream(filepath: string): Readable { - if (filepath === 'ERROR') { - throw new Error('MOCK ERROR - Invalid Path'); - } - const readableStream = new Readable(); - const streamData = filepath.split(''); - let cursor = 0; - - readableStream._read = function(size) { - const current = streamData[cursor++]; - if (typeof current === 'undefined') { - return this.push(null); - } - this.push(current); - }; - - return readableStream; - }, -})); +import './file_integrity.test.mocks'; import { getIntegrityHash, getIntegrityHashes } from './file_integrity'; diff --git a/x-pack/tasks/build.js b/x-pack/tasks/build.js index 82ccc9c75bd6f..59033bb40c7d3 100644 --- a/x-pack/tasks/build.js +++ b/x-pack/tasks/build.js @@ -34,7 +34,7 @@ export default (gulp, { buildTarget }) => { // As result of it, we need to move the transpiled js files for the correct folder // and in the end deleting the generated outDir from the intermediateBuildDirectory. // - //# TODO: This might be able to go away with the upgrade to babel 7 + //# TODO: This might be able to go away as soon as we upgrade the x-pack build to use babel7 await moveFiles( gulp, resolve(buildRoot, 'x-pack/build/plugin/kibana/x-pack/**/!(*.test).js'), diff --git a/x-pack/test/plugin_api_integration/plugins/task_manager/package.json b/x-pack/test/plugin_api_integration/plugins/task_manager/package.json index ede03a08a2721..ec63c512e9cd7 100644 --- a/x-pack/test/plugin_api_integration/plugins/task_manager/package.json +++ b/x-pack/test/plugin_api_integration/plugins/task_manager/package.json @@ -1,4 +1,12 @@ { "name": "sample_task_plugin", - "version": "kibana" + "version": "1.0.0", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "Apache-2.0", + "dependencies": { + "joi": "^13.5.2" + } } diff --git a/x-pack/test/saved_object_api_integration/common/services/es.js b/x-pack/test/saved_object_api_integration/common/services/es.js index f5ef3be4b4bde..af188ca5e3971 100644 --- a/x-pack/test/saved_object_api_integration/common/services/es.js +++ b/x-pack/test/saved_object_api_integration/common/services/es.js @@ -8,9 +8,8 @@ import { format as formatUrl } from 'url'; import elasticsearch from 'elasticsearch'; import shieldPlugin from '../../../../server/lib/esjs_shield_plugin'; -import { TestInvoker } from '../lib/types'; -export function EsProvider({ getService }: TestInvoker) { +export function EsProvider({ getService }) { const config = getService('config'); return new elasticsearch.Client({ diff --git a/x-pack/test_utils/jest/config.js b/x-pack/test_utils/jest/config.js index 014c3793c585d..e460c705f293c 100644 --- a/x-pack/test_utils/jest/config.js +++ b/x-pack/test_utils/jest/config.js @@ -31,11 +31,6 @@ export default { coverageReporters: [ 'html', ], - globals: { - 'ts-jest': { - skipBabel: true, - }, - }, moduleFileExtensions: [ 'js', 'json', @@ -55,8 +50,7 @@ export default { 'integration_tests/' ], transform: { - '^.+\\.js$': '/../src/dev/jest/babel_transform.js', - '^.+\\.tsx?$': '/../src/dev/jest/ts_transform.js', + '^.+\\.(js|tsx?)$': '/../src/dev/jest/babel_transform.js', '^.+\\.txt?$': 'jest-raw-loader', '^.+\\.html?$': 'jest-raw-loader', }, diff --git a/yarn.lock b/yarn.lock index e15a2219367b6..18dccaaa691cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,7 +35,7 @@ esutils "^2.0.2" js-tokens "^3.0.0" -"@babel/core@^7.1.0", "@babel/core@^7.3.4": +"@babel/core@7.3.4", "@babel/core@^7.1.0", "@babel/core@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b" integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA== @@ -259,7 +259,7 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.3", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4": +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.3", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c" integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ== @@ -596,6 +596,16 @@ resolve "^1.8.1" semver "^5.5.1" +"@babel/plugin-transform-runtime@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.3.4.tgz#57805ac8c1798d102ecd75c03b024a5b3ea9b431" + integrity sha512-PaoARuztAdd5MgeVjAxnIDAIUet5KpogqaefQvPOmPYCxYoaPhautxDh3aO8a4xHsKgT/b9gSxR0BKK1MIewPA== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + resolve "^1.8.1" + semver "^5.5.1" + "@babel/plugin-transform-shorthand-properties@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" @@ -650,6 +660,14 @@ "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" +"@babel/polyfill@7.2.5", "@babel/polyfill@^7.2.5": + version "7.2.5" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.2.5.tgz#6c54b964f71ad27edddc567d065e57e87ed7fa7d" + integrity sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug== + dependencies: + core-js "^2.5.7" + regenerator-runtime "^0.12.0" + "@babel/preset-env@^7.1.0", "@babel/preset-env@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.4.tgz#887cf38b6d23c82f19b5135298bdb160062e33e1" @@ -726,6 +744,19 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-typescript" "^7.3.2" +"@babel/register@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.0.0.tgz#fa634bae1bfa429f60615b754fc1f1d745edd827" + integrity sha512-f/+CRmaCe7rVEvcvPvxeA8j5aJhHC3aJie7YuqcMDhUOuyWLA7J/aNrTaHIzoWPEhpHA54mec4Mm8fv8KBlv3g== + dependencies: + core-js "^2.5.7" + find-cache-dir "^1.0.0" + home-or-tmp "^3.0.0" + lodash "^4.17.10" + mkdirp "^0.5.1" + pirates "^4.0.0" + source-map-support "^0.5.9" + "@babel/runtime@7.0.0-beta.54": version "7.0.0-beta.54" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0-beta.54.tgz#39ebb42723fe7ca4b3e1b00e967e80138d47cadf" @@ -741,6 +772,13 @@ dependencies: regenerator-runtime "^0.12.0" +"@babel/runtime@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" + integrity sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g== + dependencies: + regenerator-runtime "^0.12.0" + "@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" @@ -1606,45 +1644,45 @@ resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.49.tgz#92e33d13f74c895cb9a7f38ba97db8431ed14bc0" integrity sha512-Benr3i5odUkvpFkOpzGqrltGdbSs+EVCkEBGXbuR7uT0VzhXKIkhem6PDzHdx5EonA+rfbB3QvP6aDOw5+zp5Q== -"@types/babel-core@^6.25.5": - version "6.25.5" - resolved "https://registry.yarnpkg.com/@types/babel-core/-/babel-core-6.25.5.tgz#7598b1287c2cb5a8e9150d60e4d4a8f2dbe29982" - integrity sha512-pecvyMrc46zY0AFYXVZWNmm/gekr7f32OBYCd9baOiIpOTFtNN0ormeWpJaG7p+MEzncUvNtJdYql94dZYZGsw== - dependencies: - "@types/babel-generator" "*" - "@types/babel-template" "*" - "@types/babel-traverse" "*" - "@types/babel-types" "*" - "@types/babylon" "*" +"@types/babel-types@*", "@types/babel-types@^7.0.0": + version "7.0.4" + resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.4.tgz#bfd5b0d0d1ba13e351dff65b6e52783b816826c8" + integrity sha512-WiZhq3SVJHFRgRYLXvpf65XnV6ipVHhnNaNvE8yCimejrGglkg38kEj0JcizqwSHxmPSjcTlig/6JouxLGEhGw== -"@types/babel-generator@*": - version "6.25.2" - resolved "https://registry.yarnpkg.com/@types/babel-generator/-/babel-generator-6.25.2.tgz#fa13653ec2d34a4037be9c34dec32ae75bea04cc" - integrity sha512-W7PQkeDlYOqJblfNeqZARwj4W8nO+ZhQQZksU8+wbaKuHeUdIVUAdREO/Qb0FfNr3CY5Sq1gNtqsyFeZfS3iSw== +"@types/babel__core@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.0.tgz#710f2487dda4dcfd010ca6abb2b4dc7394365c51" + integrity sha512-wJTeJRt7BToFx3USrCDs2BhEi4ijBInTQjOIukj6a/5tEkwpFMVZ+1ppgmE+Q/FQyc5P/VWUbx7I9NELrKruHA== dependencies: - "@types/babel-types" "*" + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" -"@types/babel-template@*": - version "6.25.1" - resolved "https://registry.yarnpkg.com/@types/babel-template/-/babel-template-6.25.1.tgz#03e23a893c16bab2ec00200ab51feccf488cae78" - integrity sha512-teJYxh35PbBaf9OY6YwLSQ7pRiWRnHCHmlqwfVSfexOsqHUf6hpNZ4FG9PfgnpBM1VRzRJVQF3SqqOtkcNrBZQ== +"@types/babel__generator@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.0.2.tgz#d2112a6b21fad600d7674274293c85dce0cb47fc" + integrity sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ== dependencies: - "@types/babel-types" "*" - "@types/babylon" "*" + "@babel/types" "^7.0.0" -"@types/babel-traverse@*": - version "6.25.4" - resolved "https://registry.yarnpkg.com/@types/babel-traverse/-/babel-traverse-6.25.4.tgz#269af6a25c80419b635c8fa29ae42b0d5ce2418c" - integrity sha512-+/670NaZE7qPvdh8EtGds32/2uHFKE5JeS+7ePH6nGwF8Wj8r671/RkTiJQP2k22nFntWEb9xQ11MFj7xEqI0g== +"@types/babel__template@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" + integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== dependencies: - "@types/babel-types" "*" + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" -"@types/babel-types@*", "@types/babel-types@^7.0.0": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.4.tgz#bfd5b0d0d1ba13e351dff65b6e52783b816826c8" - integrity sha512-WiZhq3SVJHFRgRYLXvpf65XnV6ipVHhnNaNvE8yCimejrGglkg38kEj0JcizqwSHxmPSjcTlig/6JouxLGEhGw== +"@types/babel__traverse@*": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.6.tgz#328dd1a8fc4cfe3c8458be9477b219ea158fd7b2" + integrity sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw== + dependencies: + "@babel/types" "^7.3.0" -"@types/babylon@*", "@types/babylon@6.16.3", "@types/babylon@^6.16.2": +"@types/babylon@6.16.3", "@types/babylon@^6.16.2": version "6.16.3" resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.3.tgz#c2937813a89fcb5e79a00062fc4a8b143e7237bb" integrity sha512-lyJ8sW1PbY3uwuvpOBZ9zMYKshMnQpXmeDHh8dj9j2nJm/xrW0FgB5gLSYOArj5X0IfaXnmhFoJnhS4KbqIMug== @@ -1816,10 +1854,10 @@ "@types/cheerio" "*" "@types/react" "*" -"@types/eslint@^4.16.2": - version "4.16.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-4.16.2.tgz#30f4f026019eb78a6ef12f276b75cd16ea2afb27" - integrity sha512-gCqhoFlyLic8Ux1OQt9cjlPbXk/dS7zPpofazBkie6SWCl+e1IEZBgLqyakm27nh0/uSZYW2TqkBusV9fLmztw== +"@types/eslint@^4.16.6": + version "4.16.6" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-4.16.6.tgz#96d4ecddbea618ab0b55eaf0dffedf387129b06c" + integrity sha512-GL7tGJig55FeclpOytU7nCCqtR143jBoC7AUdH0DO9xBSIFiNNUFCY/S3KNWsHeQJuU3hjw/OC1+kRTFNXqUZQ== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -2842,19 +2880,17 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" -acorn-jsx@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e" - integrity sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw== - dependencies: - acorn "^5.0.3" +acorn-jsx@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" + integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== acorn-walk@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.0.1.tgz#c7827bdbb8e21aa97b609adfa225400d9ae348ba" integrity sha512-PqVQ8c6a3kyqdsUZlC7nljp3FFuxipBRHKu+7C1h8QygBFlzTaDX5HD383jej3Peed+1aDG8HwkfB1Z1HMNPkw== -acorn@5.X, acorn@^5.0.3, acorn@^5.5.0, acorn@^5.6.0, acorn@^5.6.2, acorn@^5.7.1: +acorn@5.X, acorn@^5.0.3, acorn@^5.5.0, acorn@^5.6.2, acorn@^5.7.1: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== @@ -2879,6 +2915,11 @@ acorn@^6.0.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.4.tgz#77377e7353b72ec5104550aa2d2097a2fd40b754" integrity sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg== +acorn@^6.0.7: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" + integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== + address@1.0.3, address@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" @@ -2961,7 +3002,7 @@ ajv-keywords@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= -ajv-keywords@^3.0.0, ajv-keywords@^3.1.0: +ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= @@ -2984,7 +3025,7 @@ ajv@^5.0.0, ajv@^5.1.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ajv@^6.0.1, ajv@^6.1.0, ajv@^6.1.1, ajv@^6.5.3, ajv@^6.5.5: +ajv@^6.1.0, ajv@^6.1.1, ajv@^6.5.5: version "6.5.5" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.5.tgz#cf97cdade71c6399a92c6d6c4177381291b781a1" integrity sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg== @@ -2994,6 +3035,16 @@ ajv@^6.0.1, ajv@^6.1.0, ajv@^6.1.1, ajv@^6.5.3, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.9.1: + version "6.9.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.2.tgz#4927adb83e7f48e5a32b45729744c71ec39c9c7b" + integrity sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -3108,6 +3159,11 @@ ansi-escapes@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" integrity sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ== +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + ansi-gray@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" @@ -3901,7 +3957,7 @@ axios@^0.18.0: follow-redirects "^1.3.0" is-buffer "^1.1.5" -axobject-query@^2.0.1: +axobject-query@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9" integrity sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww== @@ -3913,28 +3969,6 @@ b64@4.x.x: resolved "https://registry.yarnpkg.com/b64/-/b64-4.0.0.tgz#c37f587f0a383c7019e821120e8c3f58f0d22772" integrity sha512-EhmUQodKB0sdzPPrbIWbGqA5cQeTWxYrAgNeeT1rLZWtD3tbNTnphz8J4vkXI3cPgBNlXBjzEbzDzq0Nwi4f9A== -babel-cli@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1" - integrity sha1-UCq1SHTX24itALiHoGODzgPQAvE= - dependencies: - babel-core "^6.26.0" - babel-polyfill "^6.26.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - commander "^2.11.0" - convert-source-map "^1.5.0" - fs-readdir-recursive "^1.0.0" - glob "^7.1.2" - lodash "^4.17.4" - output-file-sync "^1.1.2" - path-is-absolute "^1.0.1" - slash "^1.0.0" - source-map "^0.5.6" - v8flags "^2.1.1" - optionalDependencies: - chokidar "^1.6.1" - babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -3944,60 +3978,10 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@6.26.3, babel-core@^6.26.3: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-core@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" - integrity sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g= - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.0" - debug "^2.6.8" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.7" - slash "^1.0.0" - source-map "^0.5.6" - -babel-eslint@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-9.0.0.tgz#7d9445f81ed9f60aff38115f838970df9f2b6220" - integrity sha512-itv1MwE3TMbY0QtNfeL7wzak1mV47Uy+n6HtSOO4Xd7rvmO+tsGQSgyOEEgo6Y2vHZKZphaoelNeSVj4vkLA1g== +babel-eslint@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed" + integrity sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ== dependencies: "@babel/code-frame" "^7.0.0" "@babel/parser" "^7.0.0" @@ -4020,104 +4004,16 @@ babel-generator@^6.18.0: source-map "^0.5.7" trim-right "^1.0.1" -babel-generator@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" - integrity sha1-rBriAHC3n248odMmlhMFN3TyDcU= - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.6" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-builder-react-jsx@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" - integrity sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA= - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - esutils "^2.0.2" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - babel-helper-evaluate-path@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz#a62fa9c4e64ff7ea5cea9353174ef023a900a67c" integrity sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA== -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babel-helper-flip-expressions@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz#3696736a128ac18bc25254b5f40a22ceb3c1d3fd" integrity sha1-NpZzahKKwYvCUlS19AoizrPB0/0= -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - babel-helper-is-nodes-equiv@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz#34e9b300b1479ddd98ec77ea0bbe9342dfe39684" @@ -4133,72 +4029,16 @@ babel-helper-mark-eval-scopes@^0.4.3: resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz#d244a3bef9844872603ffb46e22ce8acdf551562" integrity sha1-0kSjvvmESHJgP/tG4izorN9VFWI= -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babel-helper-remove-or-void@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz#a4f03b40077a0ffe88e45d07010dee241ff5ae60" integrity sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA= -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babel-helper-to-multiple-sequence-expressions@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz#a3f924e3561882d42fcf48907aa98f7979a4588d" integrity sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA== -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-jest@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1" - integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew== - dependencies: - babel-plugin-istanbul "^4.1.6" - babel-preset-jest "^23.2.0" - babel-jest@^24.1.0: version "24.1.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.1.0.tgz#441e23ef75ded3bd547e300ac3194cef87b55190" @@ -4209,14 +4049,15 @@ babel-jest@^24.1.0: chalk "^2.4.2" slash "^2.0.0" -babel-loader@7.1.5, babel-loader@^7.1.5: - version "7.1.5" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68" - integrity sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw== +babel-loader@8.0.5, babel-loader@^8.0.5: + version "8.0.5" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.5.tgz#225322d7509c2157655840bba52e46b6c2f2fe33" + integrity sha512-NTnHnVRd2JnRqPC0vW+iOQWU5pchDbYXsG2E6DMXEpMfUcQKclF9gmf3G3ZMhzG7IG9ji4coL0cm+FxeWxDpnw== dependencies: - find-cache-dir "^1.0.0" + find-cache-dir "^2.0.0" loader-utils "^1.0.2" mkdirp "^0.5.1" + util.promisify "^1.0.0" babel-messages@^6.23.0: version "6.23.0" @@ -4225,40 +4066,24 @@ babel-messages@^6.23.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-add-module-exports@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25" - integrity sha1-mumh9KjcZ/DN7E9K7aHkOl/2XiU= - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= - dependencies: - babel-runtime "^6.22.0" +babel-plugin-add-module-exports@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.0.tgz#72b5424d941a336c6a35357f373d8b8366263031" + integrity sha512-m0sMxPL4FaN2K69GQgaRJa4Ny15qKSdoknIcpN+gz+NaJlAW9pge/povs13tPYsKDboflrEQC+/3kfIsONBTaw== + optionalDependencies: + chokidar "^2.0.4" -babel-plugin-inline-react-svg@^0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/babel-plugin-inline-react-svg/-/babel-plugin-inline-react-svg-0.5.4.tgz#bc818f351cd9d78f5b3bfa7cc1da5f83e7b4010a" - integrity sha512-Pr/J5kicFEpIvwooR3mytJWXfyGXoP4gp4QzTdN0jLoa7lU2OJVyhHMm17ekA3okxwbLaQehSc0kV/UVrj343w== +babel-plugin-inline-react-svg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-inline-react-svg/-/babel-plugin-inline-react-svg-1.0.1.tgz#1457edae1035a12b3c5026ef28a1239edc71d2a2" + integrity sha512-vTsG/L2cUN4XRJdJ1scYXMSBlgAxkZm/tgo1Lo/FulbPADztEtVOPUNuNDeEoRHZCz9RC0ZHXdVSJ/GaqahF/Q== dependencies: - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babylon "^6.18.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/parser" "^7.0.0" lodash.isplainobject "^4.0.6" resolve "^1.8.1" svgo "^0.7.2" -babel-plugin-istanbul@^4.1.6: - version "4.1.6" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45" - integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ== - dependencies: - babel-plugin-syntax-object-rest-spread "^6.13.0" - find-up "^2.1.0" - istanbul-lib-instrument "^1.10.1" - test-exclude "^4.2.1" - babel-plugin-istanbul@^5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.1.tgz#7981590f1956d75d67630ba46f0c22493588c893" @@ -4268,11 +4093,6 @@ babel-plugin-istanbul@^5.1.0: istanbul-lib-instrument "^3.0.0" test-exclude "^5.0.0" -babel-plugin-jest-hoist@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167" - integrity sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc= - babel-plugin-jest-hoist@^24.1.0: version "24.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.1.0.tgz#dfecc491fb15e2668abbd690a697a8fd1411a7f8" @@ -4360,10 +4180,10 @@ babel-plugin-minify-type-constructors@^0.4.3: dependencies: babel-helper-is-void-0 "^0.4.3" -babel-plugin-mock-imports@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/babel-plugin-mock-imports/-/babel-plugin-mock-imports-0.0.5.tgz#caa865f017d8972fe47772e0fb57f2924e5ce3c5" - integrity sha1-yqhl8BfYly/kd3Lg+1fykk5c48U= +babel-plugin-mock-imports@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-mock-imports/-/babel-plugin-mock-imports-1.0.1.tgz#1476ed4de911347d344fc81caab4beced80804b1" + integrity sha512-Nu4unCGKeqOfLlfnLPnv/pEHancdAGTqFqyArZ27gsKIiKxeZvMr87IHB8BxhMu3Bfc8fA8bx7hWt32aZbEwpQ== babel-plugin-react-docgen@^2.0.0: version "2.0.0" @@ -4373,78 +4193,10 @@ babel-plugin-react-docgen@^2.0.0: lodash "^4.17.10" react-docgen "^3.0.0-rc.1" -babel-plugin-require-context-hook@^1.0.0: +"babel-plugin-require-context-hook@npm:babel-plugin-require-context-hook-babel7@^1.0.0": version "1.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-require-context-hook/-/babel-plugin-require-context-hook-1.0.0.tgz#3f0e7cce87c338f53639b948632fd4e73834632d" - integrity sha512-EMZD1563QUqLhzrqcThk759RhuNVX/ZJdrtGK6drwzgvnR+ARjWyXIHPbu+tUNaMGtPz/gQeAM2M6VUw2UiUeA== - -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= - -babel-plugin-syntax-async-generators@^6.5.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - integrity sha1-a8lj67FuzLrmuStZbrfzXDQqi5o= - -babel-plugin-syntax-class-properties@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= - -babel-plugin-syntax-flow@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" - integrity sha1-TDqyCiryaqIM0lmVw5jE63AxDI0= - -babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= - -babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= - -babel-plugin-transform-async-generator-functions@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" - integrity sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds= - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-generators "^6.5.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-class-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= - dependencies: - babel-helper-function-name "^6.24.1" - babel-plugin-syntax-class-properties "^6.8.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-require-context-hook-babel7/-/babel-plugin-require-context-hook-babel7-1.0.0.tgz#1273d4cee7e343d0860966653759a45d727e815d" + integrity sha512-kez0BAN/cQoyO1Yu1nre1bQSYZEF93Fg7VQiBHFfMWuaZTy7vJSTT4FY68FwHTYG53Nyt0A7vpSObSVxwweQeQ== babel-plugin-transform-define@^1.3.1: version "1.3.1" @@ -4454,213 +4206,6 @@ babel-plugin-transform-define@^1.3.1: lodash "^4.17.11" traverse "0.6.6" -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" - integrity sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo= - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-flow-strip-types@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" - integrity sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988= - dependencies: - babel-plugin-syntax-flow "^6.18.0" - babel-runtime "^6.22.0" - babel-plugin-transform-inline-consecutive-adds@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz#323d47a3ea63a83a7ac3c811ae8e6941faf2b0d1" @@ -4681,14 +4226,6 @@ babel-plugin-transform-minify-booleans@^6.9.4: resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz#acbb3e56a3555dd23928e4b582d285162dd2b198" integrity sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg= -babel-plugin-transform-object-rest-spread@^6.22.0, babel-plugin-transform-object-rest-spread@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.26.0" - babel-plugin-transform-property-literals@^6.9.4: version "6.9.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz#98c1d21e255736573f93ece54459f6ce24985d39" @@ -4696,49 +4233,10 @@ babel-plugin-transform-property-literals@^6.9.4: dependencies: esutils "^2.0.2" -babel-plugin-transform-react-display-name@^6.23.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" - integrity sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-self@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" - integrity sha1-322AqdomEqEh5t3XVYvL7PBuY24= - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-source@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" - integrity sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY= - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" - integrity sha1-hAoCjn30YN/DotKfDA2R9jduZqM= - dependencies: - babel-helper-builder-react-jsx "^6.24.1" - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-remove-prop-types@^0.4.14: - version "0.4.15" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.15.tgz#7ba830e77276a0e788cd58ea527b5f70396e12a7" - integrity sha512-bFxxYdkZBwTjTgtZEPTLqu9g8Ajz8x8uEP/O1iVuaZIz2RuxJ2gtx0EXDJRonC++KGsgsW/4Hqvk4KViEtE2nw== - -babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= - dependencies: - regenerator-transform "^0.10.0" +babel-plugin-transform-react-remove-prop-types@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" + integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== babel-plugin-transform-regexp-constructors@^0.4.3: version "0.4.3" @@ -4762,41 +4260,22 @@ babel-plugin-transform-remove-undefined@^0.5.0: dependencies: babel-helper-evaluate-path "^0.5.0" -babel-plugin-transform-runtime@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee" - integrity sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4= - dependencies: - babel-runtime "^6.22.0" - babel-plugin-transform-simplify-comparison-operators@^6.9.4: version "6.9.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz#f62afe096cab0e1f68a2d753fdf283888471ceb9" - integrity sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk= - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" + integrity sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk= babel-plugin-transform-undefined-to-void@^6.9.4: version "6.9.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz#be241ca81404030678b748717322b89d0c8fe280" integrity sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA= -babel-polyfill@6.20.0: - version "6.20.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.20.0.tgz#de4a371006139e20990aac0be367d398331204e7" - integrity sha1-3ko3EAYTniCZCqwL42fTmDMSBOc= - dependencies: - babel-runtime "^6.20.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" +babel-plugin-typescript-strip-namespaces@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-typescript-strip-namespaces/-/babel-plugin-typescript-strip-namespaces-1.1.1.tgz#160433b17e424b57cf72e3b4d8f08195ad28d7fd" + integrity sha512-dVB9caEANbEVwUylL8g3lsYU5JjaXE2KNIVLib3KVcGJF32QunxvQqP6kf+lzW/fyDed/zWD/e/hdyimyc/79Q== -babel-polyfill@6.26.0, babel-polyfill@^6.26.0: +babel-polyfill@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= @@ -4805,87 +4284,6 @@ babel-polyfill@6.26.0, babel-polyfill@^6.26.0: core-js "^2.5.0" regenerator-runtime "^0.10.5" -babel-preset-env@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^3.2.6" - invariant "^2.2.2" - semver "^5.3.0" - -babel-preset-es2015@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - integrity sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk= - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.24.1" - babel-plugin-transform-es2015-classes "^6.24.1" - babel-plugin-transform-es2015-computed-properties "^6.24.1" - babel-plugin-transform-es2015-destructuring "^6.22.0" - babel-plugin-transform-es2015-duplicate-keys "^6.24.1" - babel-plugin-transform-es2015-for-of "^6.22.0" - babel-plugin-transform-es2015-function-name "^6.24.1" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-plugin-transform-es2015-modules-systemjs "^6.24.1" - babel-plugin-transform-es2015-modules-umd "^6.24.1" - babel-plugin-transform-es2015-object-super "^6.24.1" - babel-plugin-transform-es2015-parameters "^6.24.1" - babel-plugin-transform-es2015-shorthand-properties "^6.24.1" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.24.1" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.22.0" - babel-plugin-transform-es2015-unicode-regex "^6.24.1" - babel-plugin-transform-regenerator "^6.24.1" - -babel-preset-flow@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" - integrity sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0= - dependencies: - babel-plugin-transform-flow-strip-types "^6.22.0" - -babel-preset-jest@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46" - integrity sha1-jsegOhOPABoaj7HoETZSvxpV2kY= - dependencies: - babel-plugin-jest-hoist "^23.2.0" - babel-plugin-syntax-object-rest-spread "^6.13.0" - babel-preset-jest@^24.1.0: version "24.1.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.1.0.tgz#83bc564fdcd4903641af65ec63f2f5de6b04132e" @@ -4923,43 +4321,7 @@ babel-preset-minify@^0.5.0: babel-plugin-transform-undefined-to-void "^6.9.4" lodash.isplainobject "^4.0.6" -babel-preset-react@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" - integrity sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A= - dependencies: - babel-plugin-syntax-jsx "^6.3.13" - babel-plugin-transform-react-display-name "^6.23.0" - babel-plugin-transform-react-jsx "^6.24.1" - babel-plugin-transform-react-jsx-self "^6.22.0" - babel-plugin-transform-react-jsx-source "^6.22.0" - babel-preset-flow "^6.23.0" - -babel-preset-stage-3@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" - integrity sha1-g2raCp56f6N8sTj7kyb4eTSkg5U= - dependencies: - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-generator-functions "^6.24.1" - babel-plugin-transform-async-to-generator "^6.24.1" - babel-plugin-transform-exponentiation-operator "^6.24.1" - babel-plugin-transform-object-rest-spread "^6.22.0" - -babel-register@6.26.0, babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@6.x.x, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.20.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0, babel-runtime@^6.5.0: +babel-runtime@6.x.x, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0, babel-runtime@^6.5.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= @@ -4972,7 +4334,7 @@ babel-standalone@^6.26.0: resolved "https://registry.yarnpkg.com/babel-standalone/-/babel-standalone-6.26.0.tgz#15fb3d35f2c456695815ebf1ed96fe7f015b6886" integrity sha1-Ffs9NfLEVmlYFevx7Zb+fwFbaIY= -babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: +babel-template@^6.16.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= @@ -4983,7 +4345,7 @@ babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: babylon "^6.18.0" lodash "^4.17.4" -babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: +babel-traverse@^6.18.0, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= @@ -5007,7 +4369,7 @@ babel-types@7.0.0-beta.3: lodash "^4.2.0" to-fast-properties "^2.0.0" -babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: +babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= @@ -5017,13 +4379,6 @@ babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24. lodash "^4.17.4" to-fast-properties "^1.0.3" -"babel7-plugin-add-module-exports@npm:babel-plugin-add-module-exports@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.0.tgz#72b5424d941a336c6a35357f373d8b8366263031" - integrity sha512-m0sMxPL4FaN2K69GQgaRJa4Ny15qKSdoknIcpN+gz+NaJlAW9pge/povs13tPYsKDboflrEQC+/3kfIsONBTaw== - optionalDependencies: - chokidar "^2.0.4" - babylon@7.0.0-beta.47: version "7.0.0-beta.47" resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.47.tgz#6d1fa44f0abec41ab7c780481e62fd9aafbdea80" @@ -5554,14 +4909,6 @@ browserslist@4.1.1: electron-to-chromium "^1.3.62" node-releases "^1.0.0-alpha.11" -browserslist@^3.2.6: - version "3.2.8" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== - dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" - browserslist@^4.0.1, browserslist@^4.3.4: version "4.4.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.4.1.tgz#42e828954b6b29a7a53e352277be429478a69062" @@ -5637,7 +4984,7 @@ buffer-fill@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= -buffer-from@^1.0.0, buffer-from@^1.1.0: +buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== @@ -5939,7 +5286,7 @@ caniuse-db@^1.0.30000539, caniuse-db@^1.0.30000597: resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000813.tgz#e0a1c603f8880ad787b2a35652b2733f32a5e29a" integrity sha1-4KHGA/iICteHsqNWUrJzPzKl4po= -caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000872, caniuse-lite@^1.0.30000929: +caniuse-lite@^1.0.30000872, caniuse-lite@^1.0.30000929: version "1.0.30000932" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000932.tgz#d01763e9ce77810962ca7391ff827b5949ce4272" integrity sha512-4bghJFItvzz8m0T3lLZbacmEY9X1Z2AtIzTr7s7byqZIOumASfr4ynDx7rtm0J85nDmx8vsgR6vnaSoeU8Oh0A== @@ -6176,6 +5523,11 @@ chardet@^0.5.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.5.0.tgz#fe3ac73c00c3d865ffcc02a0682e2c20b6a06029" integrity sha512-9ZTaoBaePSCFvNlNGrsyI8ZVACP2svUtq0DkM7t4K2ClAa96sqOIRjAzDTc8zXzFt1cZR46rRzLTiHFSJ+Qw0g== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + checksum@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/checksum/-/checksum-0.1.1.tgz#dc6527d4c90be8560dbd1ed4cecf3297d528e9e9" @@ -6233,22 +5585,6 @@ chokidar@1.6.0: optionalDependencies: fsevents "^1.0.0" -chokidar@^1.6.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= - dependencies: - anymatch "^1.3.0" - async-each "^1.0.0" - glob-parent "^2.0.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^2.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - optionalDependencies: - fsevents "^1.0.0" - chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4: version "2.1.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.2.tgz#9c23ea40b01638439e0513864d362aeacc5ad058" @@ -6558,11 +5894,6 @@ cloneable-readable@^1.0.0: process-nextick-args "^2.0.0" readable-stream "^2.3.5" -closest-file-data@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/closest-file-data/-/closest-file-data-0.1.4.tgz#975f87c132f299d24a0375b9f63ca3fb88f72b3a" - integrity sha1-l1+HwTLymdJKA3W59jyj+4j3Kzo= - cmd-shim@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb" @@ -7054,13 +6385,6 @@ convert-source-map@1.X, convert-source-map@^1.1.0, convert-source-map@^1.4.0, co resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" integrity sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU= -convert-source-map@^1.5.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== - dependencies: - safe-buffer "~5.1.1" - convex-hull@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/convex-hull/-/convex-hull-1.0.3.tgz#20a3aa6ce87f4adea2ff7d17971c9fc1c67e1fff" @@ -7924,7 +7248,7 @@ debug@3.X, debug@^3.1.0, debug@^3.2.5: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -8365,6 +7689,13 @@ doctrine@^2.0.0, doctrine@^2.1.0: dependencies: esutils "^2.0.2" +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + doctypes@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" @@ -8683,11 +8014,6 @@ electron-to-chromium@^1.3.103: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.108.tgz#2e79a6fcaa4b3e7c75abf871505bda8e268c910e" integrity sha512-/QI4hMpAh48a1Sea6PALGv+kuVne9A2EWGd8HrWHMdYhIzGtbhVVHh6heL5fAzGaDnZuPyrlWJRl8WPm4RyiQQ== -electron-to-chromium@^1.3.47: - version "1.3.82" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.82.tgz#7d13ae4437d2a783de3f4efba96b186c540b67b1" - integrity sha512-NI4nB2IWGcU4JVT1AE8kBb/dFor4zjLHMLsOROPahppeHrR0FG5uslxMmkp/thO1MvPjM2xhlKoY29/I60s0ew== - electron-to-chromium@^1.3.62: version "1.3.67" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.67.tgz#5e8f3ffac89b4b0402c7e1a565be06f3a109abbc" @@ -8723,10 +8049,10 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -emoji-regex@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.5.1.tgz#9baea929b155565c11ea41c6626eaa65cef992c2" - integrity sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ== +emoji-regex@^7.0.1, emoji-regex@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== emojis-list@^2.0.0: version "2.1.0" @@ -8811,7 +8137,7 @@ engine.io@~3.2.0: engine.io-parser "~2.1.0" ws "~3.3.1" -enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: +enhanced-resolve@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== @@ -9170,14 +8496,14 @@ escope@^3.6.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-config-prettier@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-3.1.0.tgz#2c26d2cdcfa3a05f0642cd7e6e4ef3316cdabfa2" - integrity sha512-QYGfmzuc4q4J6XIhlp8vRKdI/fI0tQfQPy1dME3UOLprE+v4ssH/3W9LM2Q7h5qBcy5m0ehCrBDU2YF8q6OY8w== +eslint-config-prettier@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-4.1.0.tgz#181364895899fff9fd3605fecb5c4f20e7d5f395" + integrity sha512-zILwX9/Ocz4SV2vX7ox85AsrAgXV3f2o2gpIicdMIOra48WYqgUnWNH/cR/iHtmD2Vb3dLSC3LiEJnS05Gkw7w== dependencies: get-stdin "^6.0.0" -eslint-import-resolver-node@^0.3.1, eslint-import-resolver-node@^0.3.2: +eslint-import-resolver-node@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== @@ -9201,62 +8527,62 @@ eslint-import-resolver-webpack@^0.10.1: resolve "^1.4.0" semver "^5.3.0" -eslint-module-utils@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" - integrity sha1-snA2LNiLGkitMIl2zn+lTphBF0Y= +eslint-module-utils@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz#546178dab5e046c8b562bbb50705e2456d7bda49" + integrity sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w== dependencies: debug "^2.6.8" - pkg-dir "^1.0.0" + pkg-dir "^2.0.0" -eslint-plugin-babel@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.2.0.tgz#3041a0c26aa3ca4a0e0f2aa11591f0396790d981" - integrity sha512-9pNH/e214SN3r2nEwwTLRI27jUN4+nuLMv1+qxfDv8Za9cJ3F+aPkNinYiVeUmAmiEtOttbS32yuwRG2DREvJg== +eslint-plugin-babel@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.0.tgz#2e7f251ccc249326da760c1a4c948a91c32d0023" + integrity sha512-HPuNzSPE75O+SnxHIafbW5QB45r2w78fxqwK3HmjqIUoPfPzVrq6rD+CINU3yzoDSzEhUkX07VUphbF73Lth/w== dependencies: eslint-rule-composer "^0.3.0" -eslint-plugin-import@^2.14.0: - version "2.14.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" - integrity sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g== +eslint-plugin-import@^2.16.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz#97ac3e75d0791c4fac0e15ef388510217be7f66f" + integrity sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A== dependencies: contains-path "^0.1.0" - debug "^2.6.8" + debug "^2.6.9" doctrine "1.5.0" - eslint-import-resolver-node "^0.3.1" - eslint-module-utils "^2.2.0" - has "^1.0.1" - lodash "^4.17.4" - minimatch "^3.0.3" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.3.0" + has "^1.0.3" + lodash "^4.17.11" + minimatch "^3.0.4" read-pkg-up "^2.0.0" - resolve "^1.6.0" + resolve "^1.9.0" -eslint-plugin-jest@^21.26.2: - version "21.27.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-21.27.2.tgz#2a795b7c3b5e707df48a953d651042bd01d7b0a8" - integrity sha512-0E4OIgBJVlAmf1KfYFtZ3gYxgUzC5Eb3Jzmrc9ikI1OY+/cM8Kh72Ti7KfpeHNeD3HJNf9SmEfmvQLIz44Hrhw== +eslint-plugin-jest@^22.3.0: + version "22.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.3.0.tgz#a10f10dedfc92def774ec9bb5bfbd2fb8e1c96d2" + integrity sha512-P1mYVRNlOEoO5T9yTqOfucjOYf1ktmJ26NjwjH8sxpCFQa6IhBGr5TpKl3hcAAT29hOsRJVuMWmTsHoUVo9FoA== -eslint-plugin-jsx-a11y@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.2.tgz#69bca4890b36dcf0fe16dd2129d2d88b98f33f88" - integrity sha512-7gSSmwb3A+fQwtw0arguwMdOdzmKUgnUcbSNlo+GjKLAQFuC2EZxWqG9XHRI8VscBJD5a8raz3RuxQNFW+XJbw== +eslint-plugin-jsx-a11y@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.1.tgz#4ebba9f339b600ff415ae4166e3e2e008831cf0c" + integrity sha512-cjN2ObWrRz0TTw7vEcGQrx+YltMvZoOEx4hWU8eEERDnBIU00OTq7Vr+jA7DFKxiwLNv4tTh5Pq2GUNEa8b6+w== dependencies: aria-query "^3.0.0" array-includes "^3.0.3" ast-types-flow "^0.0.7" - axobject-query "^2.0.1" + axobject-query "^2.0.2" damerau-levenshtein "^1.0.4" - emoji-regex "^6.5.1" + emoji-regex "^7.0.2" has "^1.0.3" jsx-ast-utils "^2.0.1" -eslint-plugin-mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-5.2.0.tgz#d8786d9fff8cb8b5f6e4b61e40395d6568a5c4e2" - integrity sha512-4VTX/qIoxUFRnXLNm6bEhEJyfGnGagmQzV4TWXKzkZgIYyP2FSubEdCjEFTyS/dGwSVRWCWGX7jO7BK8R0kppg== +eslint-plugin-mocha@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-5.3.0.tgz#cf3eb18ae0e44e433aef7159637095a7cb19b15b" + integrity sha512-3uwlJVLijjEmBeNyH60nzqgA1gacUWLUmcKV8PIGNvj1kwP/CTgAWQHn2ayyJVwziX+KETkr9opNwT1qD/RZ5A== dependencies: - ramda "^0.25.0" + ramda "^0.26.1" eslint-plugin-no-unsanitized@^3.0.2: version "3.0.2" @@ -9276,24 +8602,25 @@ eslint-plugin-prettier@^2.2.0: fast-diff "^1.1.1" jest-docblock "^21.0.0" -eslint-plugin-prettier@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.2.tgz#71998c60aedfa2141f7bfcbf9d1c459bf98b4fad" - integrity sha512-tGek5clmW5swrAx1mdPYM8oThrBE83ePh7LeseZHBWfHVGrHPhKn7Y5zgRMbU/9D5Td9K4CEmUPjGxA7iw98Og== +eslint-plugin-prettier@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz#19d521e3981f69dd6d14f64aec8c6a6ac6eb0b0d" + integrity sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ== dependencies: - fast-diff "^1.1.1" - jest-docblock "^21.0.0" + prettier-linter-helpers "^1.0.0" -eslint-plugin-react@^7.11.1: - version "7.11.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz#c01a7af6f17519457d6116aa94fc6d2ccad5443c" - integrity sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw== +eslint-plugin-react@^7.12.4: + version "7.12.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz#b1ecf26479d61aee650da612e425c53a99f48c8c" + integrity sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ== dependencies: array-includes "^3.0.3" doctrine "^2.1.0" has "^1.0.3" jsx-ast-utils "^2.0.1" + object.fromentries "^2.0.0" prop-types "^15.6.2" + resolve "^1.9.0" eslint-rule-composer@^0.3.0: version "0.3.0" @@ -9316,6 +8643,14 @@ eslint-scope@^4.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-scope@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.2.tgz#5f10cd6cabb1965bf479fa65745673439e21cb0e" + integrity sha512-5q1+B/ogmHl8+paxtOKx38Z8LtWkVGuNt3+GQNErqwLl6ViNp/gdJGMCjZNxZ8j/VYjDNZ2Fo+eQc1TAVPIzbg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-utils@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" @@ -9365,48 +8700,46 @@ eslint@^2.7.0: text-table "~0.2.0" user-home "^2.0.0" -eslint@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.6.0.tgz#b6f7806041af01f71b3f1895cbb20971ea4b6223" - integrity sha512-/eVYs9VVVboX286mBK7bbKnO1yamUy2UCRjiY6MryhQL2PaaXCExsCQ2aO83OeYRhU2eCU/FMFP+tVMoOrzNrA== +eslint@^5.15.1: + version "5.15.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.15.1.tgz#8266b089fd5391e0009a047050795b1d73664524" + integrity sha512-NTcm6vQ+PTgN3UBsALw5BMhgO6i5EpIjQF/Xb5tIh3sk9QhrFafujUOczGz4J24JBlzWclSB9Vmx8d+9Z6bFCg== dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.5.3" + ajv "^6.9.1" chalk "^2.1.0" cross-spawn "^6.0.5" - debug "^3.1.0" - doctrine "^2.1.0" - eslint-scope "^4.0.0" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.2" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" - espree "^4.0.0" + espree "^5.0.1" esquery "^1.0.1" esutils "^2.0.2" - file-entry-cache "^2.0.0" + file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" glob "^7.1.2" globals "^11.7.0" ignore "^4.0.6" + import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.1.0" - is-resolvable "^1.1.0" + inquirer "^6.2.2" js-yaml "^3.12.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.5" + lodash "^4.17.11" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" - pluralize "^7.0.0" progress "^2.0.0" - regexpp "^2.0.0" - require-uncached "^1.0.3" + regexpp "^2.0.1" semver "^5.5.1" strip-ansi "^4.0.0" strip-json-comments "^2.0.1" - table "^4.0.3" + table "^5.2.3" text-table "^0.2.0" esm@^3.0.84: @@ -9422,13 +8755,14 @@ espree@^3.1.6: acorn "^5.5.0" acorn-jsx "^3.0.0" -espree@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634" - integrity sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg== +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== dependencies: - acorn "^5.6.0" - acorn-jsx "^4.1.1" + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: version "2.7.3" @@ -9870,6 +9204,15 @@ external-editor@^3.0.0: iconv-lite "^0.4.22" tmp "^0.0.33" +external-editor@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" + integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -9983,6 +9326,11 @@ fast-diff@^1.1.1: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig== +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.0.4.tgz#a4b9f49e36175f5ef1a3456f580226a6e7abcc9e" @@ -10117,13 +9465,12 @@ file-entry-cache@^1.1.1: flat-cache "^1.2.1" object-assign "^4.0.1" -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" + flat-cache "^2.0.1" file-loader@1.1.11: version "1.1.11" @@ -10390,6 +9737,15 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + flatted@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" @@ -10595,15 +9951,6 @@ fs-extra@5.0.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" - integrity sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" @@ -10648,7 +9995,7 @@ fs-mkdirp-stream@^1.0.0: graceful-fs "^4.1.11" through2 "^2.0.3" -fs-readdir-recursive@^1.0.0, fs-readdir-recursive@^1.1.0: +fs-readdir-recursive@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== @@ -11601,10 +10948,10 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -grunt-babel@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/grunt-babel/-/grunt-babel-7.0.0.tgz#13c90c01f154dec214e0eeb5d66ac7c70cedf2d3" - integrity sha512-AFilvH/iPbnIYhL4Wx36AJQCaVEvK55xh0tujAt1DIM5tuxYxRsgUPEpwijBU147B+as/ssGuY9/6JYfTiAWpw== +grunt-babel@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/grunt-babel/-/grunt-babel-8.0.0.tgz#92ef63aafadf938c488dc2f926ac9846e0c93d1b" + integrity sha512-WuiZFvGzcyzlEoPIcY1snI234ydDWeWWV5bpnB7PZsOLHcDsxWKnrR1rMWEUsbdVPPjvIirwFNsuo4CbJmsdFQ== grunt-cli@^1.2.0, grunt-cli@~1.2.0: version "1.2.0" @@ -11723,13 +11070,13 @@ grunt@1.0.3: path-is-absolute "~1.0.0" rimraf "~2.6.2" -gulp-babel@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-7.0.1.tgz#b9c8e29fa376b36c57989db820fc1c1715bb47cb" - integrity sha512-UqHS3AdxZyJCRxqnAX603Dj3k/Wx6hzcgmav3QcxvsIFq3Y8ZkU7iXd0O+JwD5ivqCc6o0r1S7tCB/xxLnuSNw== +gulp-babel@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-8.0.0.tgz#e0da96f4f2ec4a88dd3a3030f476e38ab2126d87" + integrity sha512-oomaIqDXxFkg7lbpBou/gnUkX51/Y/M2ZfSjL2hdqXTAlSWZcgZtd2o0cOH0r/eE8LWD0+Q/PsLsr2DKOoqToQ== dependencies: plugin-error "^1.0.1" - replace-ext "0.0.1" + replace-ext "^1.0.0" through2 "^2.0.0" vinyl-sourcemaps-apply "^0.2.0" @@ -12228,13 +11575,10 @@ hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0, hoist-non-react- resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" +home-or-tmp@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-3.0.0.tgz#57a8fe24cf33cdd524860a15821ddc25c86671fb" + integrity sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs= homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: version "1.0.1" @@ -12452,7 +11796,7 @@ icalendar@0.7.1: resolved "https://registry.yarnpkg.com/icalendar/-/icalendar-0.7.1.tgz#d0d3486795f8f1c5cf4f8cafac081b4b4e7a32ae" integrity sha1-0NNIZ5X48cXPT4yvrAgbS056Mq4= -iconv-lite@0.4, iconv-lite@^0.4.17, iconv-lite@^0.4.19, iconv-lite@^0.4.22, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4, iconv-lite@^0.4.17, iconv-lite@^0.4.19, iconv-lite@^0.4.22, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -12562,6 +11906,14 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" +import-fresh@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" + integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-from@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" @@ -12690,7 +12042,7 @@ inline-style@^2.0.0: dependencies: dashify "^0.1.0" -inquirer@6.2.0, inquirer@^6.1.0, inquirer@^6.2.0: +inquirer@6.2.0, inquirer@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg== @@ -12825,6 +12177,25 @@ inquirer@^6.0.0: strip-ansi "^4.0.0" through "^2.3.6" +inquirer@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406" + integrity sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.11" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.0.0" + through "^2.3.6" + insane@2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/insane/-/insane-2.5.0.tgz#3252baec85c53b108cdf731e7962b7ce9c5cff1f" @@ -13412,7 +12783,7 @@ is-relative@^1.0.0: dependencies: is-unc-path "^1.0.0" -is-resolvable@^1.0.0, is-resolvable@^1.1.0: +is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== @@ -13613,7 +12984,7 @@ istanbul-instrumenter-loader@3.0.1: loader-utils "^1.1.0" schema-utils "^0.3.0" -istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1: +istanbul-lib-coverage@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0" integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ== @@ -13630,19 +13001,6 @@ istanbul-lib-hook@^2.0.3: dependencies: append-transform "^1.0.0" -istanbul-lib-instrument@^1.10.1: - version "1.10.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca" - integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A== - dependencies: - babel-generator "^6.18.0" - babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" - babylon "^6.18.0" - istanbul-lib-coverage "^1.2.1" - semver "^5.3.0" - istanbul-lib-instrument@^1.7.3: version "1.10.1" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz#724b4b6caceba8692d3f1f9d0727e279c401af7b" @@ -14444,7 +13802,7 @@ json3@3.3.2, json3@^3.3.2: resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= -json5@^0.5.0, json5@^0.5.1: +json5@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= @@ -15741,11 +15099,6 @@ make-dir@^1.0.0, make-dir@^1.3.0: dependencies: pify "^3.0.0" -make-error@^1.1.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.4.tgz#19978ed575f9e9545d2ff8c13e33b5d18a67d535" - integrity sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g== - make-error@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" @@ -17430,7 +16783,7 @@ os-shim@^0.1.2: resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" integrity sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc= -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= @@ -17451,15 +16804,6 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -output-file-sync@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" - integrity sha1-0KM+7+YaIF+suQCS6CZZjVJFznY= - dependencies: - graceful-fs "^4.1.4" - mkdirp "^0.5.1" - object-assign "^4.1.0" - output-file-sync@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-2.0.1.tgz#f53118282f5f553c2799541792b723a4c71430c0" @@ -17658,6 +17002,13 @@ param-case@2.1.x, param-case@^2.1.0: dependencies: no-case "^2.2.0" +parent-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" + integrity sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA== + dependencies: + callsites "^3.0.0" + parse-asn1@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" @@ -17844,7 +17195,7 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1, path-is-absolute@~1.0.0: +path-is-absolute@^1.0.0, path-is-absolute@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= @@ -17869,6 +17220,11 @@ path-parse@^1.0.5: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" integrity sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME= +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + path-root-regex@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" @@ -18046,13 +17402,6 @@ pixelmatch@4.0.2, pixelmatch@^4.0.0: dependencies: pngjs "^3.0.0" -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= - dependencies: - find-up "^1.0.0" - pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -18129,11 +17478,6 @@ pluralize@^1.2.1: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== - pn@^1.0.0, pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -18329,6 +17673,13 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + prettier@1.14.3: version "1.14.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" @@ -18373,7 +17724,7 @@ pretty-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= -private@^0.1.6, private@^0.1.7, private@^0.1.8, private@~0.1.5: +private@^0.1.6, private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== @@ -18850,10 +18201,10 @@ ramda@^0.21.0: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" integrity sha1-oAGr7bP/YQd9T/HVd9RN536NCjU= -ramda@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" - integrity sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ== +ramda@^0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" + integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== randexp@0.4.6: version "0.4.6" @@ -19919,7 +19270,7 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.10.0, regenerator-runtime@^0.10.5: +regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= @@ -19934,15 +19285,6 @@ regenerator-runtime@^0.12.0, regenerator-runtime@^0.12.1: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - regenerator-transform@^0.13.3: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb" @@ -19995,10 +19337,10 @@ regexp.prototype.flags@^1.2.0: dependencies: define-properties "^1.1.2" -regexpp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.0.tgz#b2a7534a85ca1b033bcf5ce9ff8e56d4e0755365" - integrity sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA== +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== regexpu-core@^1.0.0: version "1.0.0" @@ -20009,15 +19351,6 @@ regexpu-core@^1.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - regexpu-core@^4.1.3, regexpu-core@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.2.0.tgz#a3744fa03806cffe146dea4421a3e73bdcc47b1d" @@ -20331,7 +19664,7 @@ require-main-filename@^1.0.1: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= -require-uncached@^1.0.2, require-uncached@^1.0.3: +require-uncached@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= @@ -20432,7 +19765,7 @@ resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7: dependencies: path-parse "^1.0.5" -resolve@^1.3.2, resolve@^1.4.0, resolve@^1.6.0, resolve@^1.8.1: +resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== @@ -20446,6 +19779,13 @@ resolve@^1.5.0, resolve@^1.7.1: dependencies: path-parse "^1.0.5" +resolve@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" + integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== + dependencies: + path-parse "^1.0.6" + responselike@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -20512,18 +19852,18 @@ rimraf@2.4.3: dependencies: glob "^5.0.14" -rimraf@~2.2.6: - version "2.2.8" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" - integrity sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI= - -rimraf@~2.6.2: +rimraf@2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" +rimraf@~2.2.6: + version "2.2.8" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + integrity sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI= + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" @@ -20674,6 +20014,13 @@ rxjs@^6.2.1: dependencies: tslib "^1.9.0" +rxjs@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" + integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== + dependencies: + tslib "^1.9.0" + safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -21278,11 +20625,13 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" slide@^1.1.5, slide@~1.1.3: @@ -21443,13 +20792,6 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - source-map-support@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" @@ -21466,6 +20808,14 @@ source-map-support@^0.5.6, source-map-support@~0.5.6: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@^0.5.9: + version "0.5.10" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" + integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" @@ -21889,6 +21239,15 @@ string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" + integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.0.0" + string.prototype.matchall@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-3.0.0.tgz#66f4d8dd5c6c6cea4dffb55ec5f3184a8dd0dd59" @@ -22321,17 +21680,15 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -table@^4.0.3: - version "4.0.3" - resolved "http://registry.npmjs.org/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" - integrity sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg== +table@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" + integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ== dependencies: - ajv "^6.0.1" - ajv-keywords "^3.0.0" - chalk "^2.1.0" - lodash "^4.17.4" - slice-ansi "1.0.0" - string-width "^2.1.1" + ajv "^6.9.1" + lodash "^4.17.11" + slice-ansi "^2.1.0" + string-width "^3.0.0" tabtab@^1.3.2: version "1.3.2" @@ -22503,17 +21860,6 @@ terser@^3.8.1: source-map "~0.6.1" source-map-support "~0.5.6" -test-exclude@^4.2.1: - version "4.2.3" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20" - integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA== - dependencies: - arrify "^1.0.1" - micromatch "^2.3.11" - object-assign "^4.1.0" - read-pkg-up "^1.0.1" - require-main-filename "^1.0.1" - test-exclude@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.1.0.tgz#6ba6b25179d2d38724824661323b73e03c0c1de1" @@ -22963,46 +22309,11 @@ trunc-text@1.0.2: resolved "https://registry.yarnpkg.com/trunc-text/-/trunc-text-1.0.2.tgz#b582bb3ddea9c9adc25017d737c48ebdd2157406" integrity sha1-tYK7Pd6pya3CUBfXN8SOvdIVdAY= -ts-jest@^23.1.4: - version "23.1.4" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-23.1.4.tgz#66ac1d8d3fbf8f9a98432b11aa377aa850664b2b" - integrity sha512-9rCSxbWfoZxxeXnSoEIzRNr9hDIQ8iEJAWmSRsWhDHDT8OeuGfURhJQUE8jtJlkyEygs6rngH8RYtHz9cfjmEA== - dependencies: - closest-file-data "^0.1.4" - fs-extra "6.0.1" - json5 "^0.5.0" - lodash "^4.17.10" - -ts-loader@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.2.2.tgz#a707849b08ca754cc46f5c7053e79fe1c84caf0e" - integrity sha512-vM/TrEKXBqRYq5yLatsXyKFnYSpv53klmGtrILGlNqcMsxPVi8+e4yr1Agbu9oMZepx/4szDVn5QpFo83IQdQg== - dependencies: - chalk "^2.3.0" - enhanced-resolve "^4.0.0" - loader-utils "^1.0.2" - micromatch "^3.1.4" - semver "^5.0.1" - ts-log@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.1.3.tgz#9e30aca1baffe7693a2e4142b8f07ecb01cb8340" integrity sha512-VIk9+hzE80UjhJcSANst8LGRBpfNh32y9d3LVDMtEqcEb1x0hB71IO0aObNcLJ5VpK5tKeF9uI4pwEco03SkwA== -ts-node@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" - integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== - dependencies: - arrify "^1.0.0" - buffer-from "^1.1.0" - diff "^3.1.0" - make-error "^1.1.1" - minimist "^1.2.0" - mkdirp "^0.5.1" - source-map-support "^0.5.6" - yn "^2.0.0" - tslib@1.9.3, tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.2, tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" @@ -24115,7 +23426,7 @@ v8-compile-cache@^2.0.2: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== -v8flags@^2.0.2, v8flags@^2.1.1: +v8flags@^2.0.2: version "2.1.1" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" integrity sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ= @@ -25167,6 +24478,13 @@ write-pkg@^3.1.0: sort-keys "^2.0.0" write-json-file "^2.2.0" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" @@ -25656,11 +24974,6 @@ yeoman-generator@1.1.1: user-home "^2.0.0" yeoman-environment "^1.1.0" -yn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" - integrity sha1-5a2ryKz0CPY4X8dklWhMiOavaJo= - yo@2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/yo/-/yo-2.0.5.tgz#2f747f5d279ab777e0167b0aa63d7b607507d73d" From 8b0d1206a8e01ddd9b04a9be0bc21e0e7453de62 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Tue, 26 Mar 2019 22:15:16 +0100 Subject: [PATCH 41/96] FTR: fix 10 sec timeout in waitForDeleted (#33313) * use css selector instead of className, set implicit wait to 0 * set implicitWait to 2 sec * set default implicitWait to WAIT_FOR_EXISTS_TIME * set timeout to 1 sec, retry for query bar test * sleep 5 sec waiting zoom is finished * sleep is the only way to wait * run x-pack-ciGroup3 20x times * Revert "run x-pack-ciGroup3 20x times" This reverts commit 55482de330c8bc5872412dbcf767fab05bcb602f. --- test/functional/page_objects/home_page.js | 4 ++-- test/functional/page_objects/share_page.js | 2 +- test/functional/services/combo_box.js | 2 +- test/functional/services/find.js | 2 ++ .../web_element_wrapper/web_element_wrapper.js | 18 ++++++++---------- .../test/functional/page_objects/gis_page.js | 4 +++- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/test/functional/page_objects/home_page.js b/test/functional/page_objects/home_page.js index 7c0d2f7faba63..008a3dff69c0f 100644 --- a/test/functional/page_objects/home_page.js +++ b/test/functional/page_objects/home_page.js @@ -60,9 +60,9 @@ export function HomePageProvider({ getService }) { async _waitForSampleDataLoadingAction(id) { const sampleDataCard = await testSubjects.find(`sampleDataSetCard${id}`); await retry.try(async () => { - // waitForDeletedByClassName needs to be inside retry because it will timeout at least once + // waitForDeletedByCssSelector needs to be inside retry because it will timeout at least once // before action is complete - await sampleDataCard.waitForDeletedByClassName('euiLoadingSpinner'); + await sampleDataCard.waitForDeletedByCssSelector('.euiLoadingSpinner'); }); } diff --git a/test/functional/page_objects/share_page.js b/test/functional/page_objects/share_page.js index 777482b55771b..b9be3faae640b 100644 --- a/test/functional/page_objects/share_page.js +++ b/test/functional/page_objects/share_page.js @@ -56,7 +56,7 @@ export function SharePageProvider({ getService, getPageObjects }) { async checkShortenUrl() { const shareForm = await testSubjects.find('shareUrlForm'); await PageObjects.visualize.checkCheckbox('useShortUrl'); - await shareForm.waitForDeletedByClassName('euiLoadingSpinner'); + await shareForm.waitForDeletedByCssSelector('.euiLoadingSpinner'); } async exportAsSavedObject() { diff --git a/test/functional/services/combo_box.js b/test/functional/services/combo_box.js index b60556bacfd94..33d0efc5b3932 100644 --- a/test/functional/services/combo_box.js +++ b/test/functional/services/combo_box.js @@ -56,7 +56,7 @@ export function ComboBoxProvider({ getService }) { } async _waitForOptionsListLoading(comboBoxElement) { - await comboBoxElement.waitForDeletedByClassName('euiLoadingSpinner'); + await comboBoxElement.waitForDeletedByCssSelector('.euiLoadingSpinner'); } async getOptionsList(comboBoxSelector) { diff --git a/test/functional/services/find.js b/test/functional/services/find.js index f16765fd03f7e..16802b5f27078 100644 --- a/test/functional/services/find.js +++ b/test/functional/services/find.js @@ -309,12 +309,14 @@ export async function FindProvider({ getService }) { } async waitForDeletedByCssSelector(selector, timeout = defaultFindTimeout) { log.debug(`Find.waitForDeletedByCssSelector('${selector}') with timeout=${timeout}`); + await this._withTimeout(1000); await driver.wait(async () => { const found = await driver.findElements(By.css(selector)); return found.length === 0; }, timeout, `The element ${selector} was still present when it should have disappeared.`); + await this._withTimeout(defaultFindTimeout); } async waitForAttributeToChange(selector, attribute, value) { diff --git a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.js b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.js index 8e96c3af0cc9b..be9c88fda1aa1 100644 --- a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.js +++ b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.js @@ -389,22 +389,20 @@ export class WebElementWrapper { } /** - * Waits for all elements inside this element matching the given CSS class name to be destroyed. + * Waits for all elements inside this element matching the given CSS selector to be destroyed. * * @param {string} className * @return {Promise} */ - async waitForDeletedByClassName(className) { - await this._driver.wait(() => { - return this._webElement.findElements(this._By.className(className)).then((children) => { - if (children.length <= 0) { - return true; - } - return false; - }); + async waitForDeletedByCssSelector(selector) { + await this._driver.manage().setTimeouts({ implicit: 1000 }); + await this._driver.wait(async () => { + const found = await this._webElement.findElements(this._By.css(selector)); + return found.length === 0; }, this._defaultFindTimeout, - `The element with ${className} className was still present when it should have disappeared.`); + `The element with ${selector} selector was still present after ${this._defaultFindTimeout} sec.`); + await this._driver.manage().setTimeouts({ implicit: this._defaultFindTimeout }); } /** diff --git a/x-pack/test/functional/page_objects/gis_page.js b/x-pack/test/functional/page_objects/gis_page.js index 122e6434301a9..0f60d619f6d69 100644 --- a/x-pack/test/functional/page_objects/gis_page.js +++ b/x-pack/test/functional/page_objects/gis_page.js @@ -55,7 +55,7 @@ export function GisPageProvider({ getService, getPageObjects }) { log.debug('Wait for layers to load'); const tableOfContents = await testSubjects.find('mapLayerTOC'); await retry.try(async () => { - await tableOfContents.waitForDeletedByClassName('euiLoadingSpinner'); + await tableOfContents.waitForDeletedByCssSelector('.euiLoadingSpinner'); }); } @@ -170,6 +170,8 @@ export function GisPageProvider({ getService, getPageObjects }) { await testSubjects.setValue('zoomInput', zoom.toString()); await testSubjects.click('submitViewButton'); await this.waitForLayersToLoad(); + // there is no way to wait for canvas been reloaded + await PageObjects.common.sleep(5000); } async getView() { From 41fb553ee350d7245bf55092dc24e224fd78abb2 Mon Sep 17 00:00:00 2001 From: Sarah Hersh Date: Tue, 26 Mar 2019 17:53:35 -0400 Subject: [PATCH 42/96] edits to page headers (#33887) --- .../core/development-unit-tests.asciidoc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/development/core/development-unit-tests.asciidoc b/docs/development/core/development-unit-tests.asciidoc index 852d1fef6b32a..a738e2cf372d9 100644 --- a/docs/development/core/development-unit-tests.asciidoc +++ b/docs/development/core/development-unit-tests.asciidoc @@ -1,35 +1,37 @@ [[development-unit-tests]] === Unit Testing -We use unit tests to make sure that individual software units of Kibana perform as they were designed to. +We use unit tests to make sure that individual software units of {kib} perform as they were designed to. [float] -==== Current Frameworks +=== Current Frameworks -Kibana is migrating unit testing from `Mocha` to `Jest`. Legacy unit tests still exist in `Mocha` but all new unit tests should be written in `Jest`. +{kib} is migrating unit testing from `Mocha` to `Jest`. Legacy unit tests still exist in `Mocha` but all new unit tests should be written in `Jest`. [float] ==== Mocha (legacy) Mocha tests are contained in `__tests__` directories. -===== Running Mocha Unit Tests +*Running Mocha Unit Tests* ["source","shell"] ----------- yarn test:mocha ----------- +[float] ==== Jest Jest tests are stored in the same directory as source code files with the `.test.{js,ts,tsx}` suffix. -===== Running Jest Unit Tests +*Running Jest Unit Tests* ["source","shell"] ----------- yarn test:jest ----------- +[float] ===== Writing Jest Unit Tests In order to write those tests there are two main things you need to be aware of. @@ -39,8 +41,8 @@ test files with `babel-jest` both techniques are needed specially for the tests implemented on Typescript in order to benefit from the auto-inference types feature. - -====== Jest.mock vs Jest.doMock +[float] +===== Jest.mock vs Jest.doMock Both methods are essentially the same on their roots however the `jest.mock` calls will get hoisted to the top of the file and can only reference variables @@ -49,7 +51,8 @@ reference pretty much any variable we want, however we have to assure those refe variables are instantiated at the time we need them which lead us to the next section where we'll talk about our jest mock files pattern. -====== Jest Mock Files Pattern +[float] +===== Jest Mock Files Pattern Specially on typescript it is pretty common to have in unit tests `jest.doMock` calls which reference for example imported types. Any error From 7676f03bcac0917386e0050a4735e2f4f405bc79 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Tue, 26 Mar 2019 15:41:25 -0700 Subject: [PATCH 43/96] Fix plugin generator paths (#33728) --- .../sao_template/template/package_template.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/kbn-plugin-generator/sao_template/template/package_template.json b/packages/kbn-plugin-generator/sao_template/template/package_template.json index 7a6d0842a1649..e70755efef7fd 100644 --- a/packages/kbn-plugin-generator/sao_template/template/package_template.json +++ b/packages/kbn-plugin-generator/sao_template/template/package_template.json @@ -8,9 +8,9 @@ "templateVersion": "<%= templateVersion %>" }, "scripts": { - "preinstall": "node ../../kibana/preinstall_check", - "kbn": "node ../../kibana/scripts/kbn", - "es": "node ../../kibana/scripts/es", + "preinstall": "node ../../preinstall_check", + "kbn": "node ../../scripts/kbn", + "es": "node ../../scripts/es", "lint": "eslint .", "start": "plugin-helpers start", "test:server": "plugin-helpers test:server", @@ -19,14 +19,14 @@ }, <%_ if (generateTranslations) { _%> "dependencies": { - "@kbn/i18n": "link:../../kibana/packages/kbn-i18n" + "@kbn/i18n": "link:../../packages/kbn-i18n" }, <%_ } _%> "devDependencies": { - "@elastic/eslint-config-kibana": "link:../../kibana/packages/eslint-config-kibana", - "@elastic/eslint-import-resolver-kibana": "link:../../kibana/packages/kbn-eslint-import-resolver-kibana", + "@elastic/eslint-config-kibana": "link:../../packages/eslint-config-kibana", + "@elastic/eslint-import-resolver-kibana": "link:../../packages/kbn-eslint-import-resolver-kibana", "@kbn/expect": "1.0.0", - "@kbn/plugin-helpers": "link:../../kibana/packages/kbn-plugin-helpers", + "@kbn/plugin-helpers": "link:../../packages/kbn-plugin-helpers", "babel-eslint": "^10.0.1", "eslint": "^5.14.1", "eslint-plugin-babel": "^5.3.0", From d8c7e18bf150d599697676b5a4159d55e154fea8 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 26 Mar 2019 15:43:03 -0700 Subject: [PATCH 44/96] Instrument ILM with user action telemetry (#33089) * Track user actions for creating, updating, and deleting and index lifecycle policy. * Track user actions for attaching an index, attaching an index template, and detaching an index. * Track app load action. * Track usage of cold phase, warm phase, set priority, and freeze index. * Track retry step user action. * Track clicks on the policy name to edit it. * Refactor constants to be in root of public. * Add support to user actions API for comma-delimited action types. * Refactor rollups trackUserRequest to be easier to understand. * Use underscores instead of dashes for user action app names. * Switch from componentWillMount to componentDidMount/useEffect. - Standardize use of HashRouter within app.js to avoid calling useEffect when leaving the app. --- .../server/routes/api/user_action.ts | 13 ++-- .../apis/user_action/user_action.js | 22 +++++- .../common/constants/index.js | 17 +++++ .../common/constants/user_action.js | 37 +++++++++ .../index_lifecycle_management/index.js | 4 + .../index_lifecycle_management/public/app.js | 27 ++++--- .../constants.js => constants/index.js} | 0 .../cold_phase/cold_phase.container.js | 2 +- .../components/cold_phase/cold_phase.js | 2 +- .../delete_phase/delete_phase.container.js | 2 +- .../components/delete_phase/delete_phase.js | 2 +- .../hot_phase/hot_phase.container.js | 2 +- .../components/hot_phase/hot_phase.js | 2 +- .../edit_policy/components/min_age_input.js | 2 +- .../node_allocation/node_allocation.js | 2 +- .../components/set_priority_input.js | 2 +- .../warm_phase/warm_phase.container.js | 2 +- .../components/warm_phase/warm_phase.js | 2 +- .../sections/edit_policy/edit_policy.js | 2 +- .../components/policy_table/policy_table.js | 16 ++-- .../public/services/api.js | 25 ++++++- .../public/services/index.js | 1 + .../public/services/user_action.js | 75 +++++++++++++++++++ .../public/services/user_action.test.js | 74 ++++++++++++++++++ .../public/store/actions/lifecycle.js | 13 +++- .../public/store/actions/nodes.js | 2 +- .../public/store/actions/policies.js | 2 +- .../public/store/defaults/cold_phase.js | 2 +- .../public/store/defaults/delete_phase.js | 2 +- .../public/store/defaults/hot_phase.js | 2 +- .../public/store/defaults/warm_phase.js | 2 +- .../public/store/reducers/policies.js | 2 +- .../public/store/selectors/lifecycle.js | 2 +- .../public/store/selectors/policies.js | 2 +- .../server/usage/collector.js | 25 +++++++ .../server/usage/index.js | 7 ++ .../__jest__/components/index_table.test.js | 4 +- .../common/constants/user_action.js | 2 +- x-pack/plugins/index_management/public/app.js | 37 ++++----- .../public/register_routes.js | 5 +- x-pack/plugins/rollup/public/crud_app/app.js | 26 +++++-- .../plugins/rollup/public/crud_app/index.js | 5 +- .../crud_app/services/track_user_action.js | 12 ++- 43 files changed, 400 insertions(+), 89 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/common/constants/user_action.js rename x-pack/plugins/index_lifecycle_management/public/{store/constants.js => constants/index.js} (100%) create mode 100644 x-pack/plugins/index_lifecycle_management/public/services/user_action.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/services/user_action.test.js create mode 100644 x-pack/plugins/index_lifecycle_management/server/usage/collector.js create mode 100644 x-pack/plugins/index_lifecycle_management/server/usage/index.js diff --git a/src/legacy/core_plugins/user_action/server/routes/api/user_action.ts b/src/legacy/core_plugins/user_action/server/routes/api/user_action.ts index f7d1067e8024e..004f6e2b6953d 100644 --- a/src/legacy/core_plugins/user_action/server/routes/api/user_action.ts +++ b/src/legacy/core_plugins/user_action/server/routes/api/user_action.ts @@ -25,20 +25,23 @@ export const registerUserActionRoute = (server: Server) => { * Increment a count on an object representing a specific user action. */ server.route({ - path: '/api/user_action/{appName}/{actionType}', + path: '/api/user_action/{appName}/{actionTypes}', method: 'POST', handler: async (request: any) => { - const { appName, actionType } = request.params; + const { appName, actionTypes } = request.params; try { const { getSavedObjectsRepository } = server.savedObjects; const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); const internalRepository = getSavedObjectsRepository(callWithInternalUser); - const savedObjectId = `${appName}:${actionType}`; - // This object is created if it doesn't already exist. - await internalRepository.incrementCounter('user-action', savedObjectId, 'count'); + const incrementRequests = actionTypes.split(',').map((actionType: string) => { + const savedObjectId = `${appName}:${actionType}`; + // This object is created if it doesn't already exist. + return internalRepository.incrementCounter('user-action', savedObjectId, 'count'); + }); + await Promise.all(incrementRequests); return {}; } catch (error) { return new Boom('Something went wrong', { statusCode: error.status }); diff --git a/test/api_integration/apis/user_action/user_action.js b/test/api_integration/apis/user_action/user_action.js index db4485c8f14f3..d0be6d6482004 100644 --- a/test/api_integration/apis/user_action/user_action.js +++ b/test/api_integration/apis/user_action/user_action.js @@ -18,7 +18,6 @@ */ import expect from '@kbn/expect'; -import { get } from 'lodash'; export default function ({ getService }) { const supertest = getService('supertest'); @@ -35,9 +34,24 @@ export default function ({ getService }) { index: '.kibana', q: 'type:user-action', }).then(response => { - const doc = get(response, 'hits.hits[0]'); - expect(get(doc, '_source.user-action.count')).to.be(1); - expect(doc._id).to.be('user-action:myApp:myAction'); + const ids = response.hits.hits.map(({ _id }) => _id); + expect(ids.includes('user-action:myApp:myAction')); + }); + }); + + it('supports comma-delimited action types', async () => { + await supertest + .post('/api/user_action/myApp/myAction1,myAction2') + .set('kbn-xsrf', 'kibana') + .expect(200); + + return es.search({ + index: '.kibana', + q: 'type:user-action', + }).then(response => { + const ids = response.hits.hits.map(({ _id }) => _id); + expect(ids.includes('user-action:myApp:myAction1')); + expect(ids.includes('user-action:myApp:myAction2')); }); }); }); diff --git a/x-pack/plugins/index_lifecycle_management/common/constants/index.js b/x-pack/plugins/index_lifecycle_management/common/constants/index.js index 5525b2b86f4d1..204bf87e0ae7c 100644 --- a/x-pack/plugins/index_lifecycle_management/common/constants/index.js +++ b/x-pack/plugins/index_lifecycle_management/common/constants/index.js @@ -6,3 +6,20 @@ export const BASE_PATH = '/management/elasticsearch/index_lifecycle_management/'; export const PLUGIN_ID = 'index_lifecycle_management'; +export { + UA_APP_NAME, + USER_ACTIONS, + UA_APP_LOAD, + UA_POLICY_CREATE, + UA_POLICY_UPDATE, + UA_POLICY_DELETE, + UA_POLICY_ATTACH_INDEX, + UA_POLICY_ATTACH_INDEX_TEMPLATE, + UA_POLICY_DETACH_INDEX, + UA_CONFIG_COLD_PHASE, + UA_CONFIG_WARM_PHASE, + UA_CONFIG_SET_PRIORITY, + UA_CONFIG_FREEZE_INDEX, + UA_INDEX_RETRY_STEP, + UA_EDIT_CLICK, +} from './user_action'; diff --git a/x-pack/plugins/index_lifecycle_management/common/constants/user_action.js b/x-pack/plugins/index_lifecycle_management/common/constants/user_action.js new file mode 100644 index 0000000000000..91f28e855b067 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/common/constants/user_action.js @@ -0,0 +1,37 @@ +/* + * 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. + */ + +export const UA_APP_NAME = 'index_lifecycle_management'; + +export const UA_APP_LOAD = 'app_load'; +export const UA_POLICY_CREATE = 'policy_create'; +export const UA_POLICY_UPDATE = 'policy_update'; +export const UA_POLICY_DELETE = 'policy_delete'; +export const UA_POLICY_ATTACH_INDEX = 'policy_attach_index'; +export const UA_POLICY_ATTACH_INDEX_TEMPLATE = 'policy_attach_index_template'; +export const UA_POLICY_DETACH_INDEX = 'policy_detach_index'; +export const UA_CONFIG_COLD_PHASE = 'config_cold_phase'; +export const UA_CONFIG_WARM_PHASE = 'config_warm_phase'; +export const UA_CONFIG_SET_PRIORITY = 'config_set_priority'; +export const UA_CONFIG_FREEZE_INDEX = 'config_freeze_index'; +export const UA_INDEX_RETRY_STEP = 'index_retry_step'; +export const UA_EDIT_CLICK = 'edit_click'; + +export const USER_ACTIONS = [ + UA_APP_LOAD, + UA_POLICY_CREATE, + UA_POLICY_UPDATE, + UA_POLICY_DELETE, + UA_POLICY_ATTACH_INDEX, + UA_POLICY_ATTACH_INDEX_TEMPLATE, + UA_POLICY_DETACH_INDEX, + UA_CONFIG_COLD_PHASE, + UA_CONFIG_WARM_PHASE, + UA_CONFIG_SET_PRIORITY, + UA_CONFIG_FREEZE_INDEX, + UA_INDEX_RETRY_STEP, + UA_EDIT_CLICK, +]; diff --git a/x-pack/plugins/index_lifecycle_management/index.js b/x-pack/plugins/index_lifecycle_management/index.js index fe1fc677e102e..384293053c45f 100644 --- a/x-pack/plugins/index_lifecycle_management/index.js +++ b/x-pack/plugins/index_lifecycle_management/index.js @@ -13,6 +13,8 @@ import { registerIndexRoutes } from './server/routes/api/index'; import { registerLicenseChecker } from './server/lib/register_license_checker'; import { PLUGIN_ID } from './common/constants'; import { indexLifecycleDataEnricher } from './index_lifecycle_data'; +import { registerIndexLifecycleManagementUsageCollector } from './server/usage'; + export function indexLifecycleManagement(kibana) { return new kibana.Plugin({ config: (Joi) => { @@ -52,6 +54,8 @@ export function indexLifecycleManagement(kibana) { registerPoliciesRoutes(server); registerLifecycleRoutes(server); registerIndexRoutes(server); + registerIndexLifecycleManagementUsageCollector(server); + if ( server.config().get('xpack.ilm.ui.enabled') && server.plugins.index_management && diff --git a/x-pack/plugins/index_lifecycle_management/public/app.js b/x-pack/plugins/index_lifecycle_management/public/app.js index e316d11017a14..b644ffdcf1df4 100644 --- a/x-pack/plugins/index_lifecycle_management/public/app.js +++ b/x-pack/plugins/index_lifecycle_management/public/app.js @@ -4,18 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { HashRouter, Switch, Route, Redirect } from 'react-router-dom'; +import { BASE_PATH, UA_APP_LOAD } from '../common/constants'; import { EditPolicy } from './sections/edit_policy'; import { PolicyTable } from './sections/policy_table'; -import { BASE_PATH } from '../common/constants'; +import { trackUserAction } from './services'; -export const App = () => ( - - - - - - - -); +export const App = () => { + useEffect(() => trackUserAction(UA_APP_LOAD), []); + + return ( + + + + + + + + ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/store/constants.js b/x-pack/plugins/index_lifecycle_management/public/constants/index.js similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/store/constants.js rename to x-pack/plugins/index_lifecycle_management/public/constants/index.js diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.container.js index f6470e5c66d3c..90c30d943f68f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.container.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.container.js @@ -17,7 +17,7 @@ import { PHASE_COLD, PHASE_HOT, PHASE_ROLLOVER_ENABLED -} from '../../../../store/constants'; +} from '../../../../constants'; export const ColdPhase = connect( (state) => ({ diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js index ee8759f5f6b0f..c95ef1ee75d4e 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js @@ -22,7 +22,7 @@ import { PHASE_ENABLED, PHASE_REPLICA_COUNT, PHASE_FREEZE_ENABLED -} from '../../../../store/constants'; +} from '../../../../constants'; import { ErrableFormRow } from '../../form_errors'; import { MinAgeInput } from '../min_age_input'; import { LearnMoreLink, ActiveBadge, PhaseErrorMessage, OptionalLabel } from '../../../components'; diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.container.js index b7eb4164073c1..f7933815d9f33 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.container.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.container.js @@ -8,7 +8,7 @@ import { connect } from 'react-redux'; import { DeletePhase as PresentationComponent } from './delete_phase'; import { getPhase } from '../../../../store/selectors'; import { setPhaseData } from '../../../../store/actions'; -import { PHASE_DELETE, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../store/constants'; +import { PHASE_DELETE, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../constants'; export const DeletePhase = connect( state => ({ diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js index a10ae5ab65595..0e7663a6aef7d 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js @@ -19,7 +19,7 @@ import { import { PHASE_DELETE, PHASE_ENABLED, -} from '../../../../store/constants'; +} from '../../../../constants'; import { ActiveBadge, PhaseErrorMessage } from '../../../components'; export class DeletePhase extends PureComponent { diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.container.js index 0361d287cd402..e1ef58660525c 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.container.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.container.js @@ -11,7 +11,7 @@ import { connect } from 'react-redux'; import { HotPhase as PresentationComponent } from './hot_phase'; import { getPhase } from '../../../../store/selectors'; import { setPhaseData } from '../../../../store/actions'; -import { PHASE_HOT, PHASE_WARM, WARM_PHASE_ON_ROLLOVER } from '../../../../store/constants'; +import { PHASE_HOT, PHASE_WARM, WARM_PHASE_ON_ROLLOVER } from '../../../../constants'; export const HotPhase = connect( state => ({ diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js index ccdb2a6479b15..be1023e9042a3 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js @@ -27,7 +27,7 @@ import { PHASE_ROLLOVER_MAX_SIZE_STORED, PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS, PHASE_ROLLOVER_ENABLED, -} from '../../../../store/constants'; +} from '../../../../constants'; import { SetPriorityInput } from '../set_priority_input'; import { ErrableFormRow } from '../../form_errors'; diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js index d290a25d0636f..d52bc147138a8 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js @@ -15,7 +15,7 @@ import { import { PHASE_ROLLOVER_MINIMUM_AGE, PHASE_ROLLOVER_MINIMUM_AGE_UNITS, -} from '../../../store/constants'; +} from '../../../constants'; import { ErrableFormRow } from '../form_errors'; import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; const MinAgeInputUi = props => { diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_allocation/node_allocation.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_allocation/node_allocation.js index 60f37c4be7296..0a0f3bf9d35a7 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_allocation/node_allocation.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_allocation/node_allocation.js @@ -7,7 +7,7 @@ import React, { Component, Fragment } from 'react'; import { EuiSelect, EuiButtonEmpty, EuiCallOut, EuiSpacer, EuiLoadingSpinner } from '@elastic/eui'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; -import { PHASE_NODE_ATTRS } from '../../../../store/constants'; +import { PHASE_NODE_ATTRS } from '../../../../constants'; import { ErrableFormRow } from '../../form_errors'; import { LearnMoreLink } from '../../../components/learn_more_link'; const learnMoreLinks = ( diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js index af65348171957..3f4c32b05a2dc 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js @@ -12,7 +12,7 @@ import { } from '@elastic/eui'; import { PHASE_INDEX_PRIORITY, -} from '../../../store/constants'; +} from '../../../constants'; import { ErrableFormRow } from '../form_errors'; import { FormattedMessage } from '@kbn/i18n/react'; export const SetPriorityInput = props => { diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js index 5b66fcae24ec2..4e68a51aee931 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js @@ -13,7 +13,7 @@ import { getPhase, } from '../../../../store/selectors'; import { setPhaseData } from '../../../../store/actions'; -import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../store/constants'; +import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../constants'; export const WarmPhase = connect( state => ({ diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js index d9c9d0930daf9..b25e3db0cedab 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js @@ -26,7 +26,7 @@ import { PHASE_PRIMARY_SHARD_COUNT, PHASE_REPLICA_COUNT, PHASE_SHRINK_ENABLED, -} from '../../../../store/constants'; +} from '../../../../constants'; import { SetPriorityInput } from '../set_priority_input'; import { NodeAllocation } from '../node_allocation'; import { ErrableFormRow } from '../../form_errors'; diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js index 9daa0926b5710..8e9fcc281ad27 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js @@ -36,7 +36,7 @@ import { PHASE_DELETE, PHASE_WARM, STRUCTURE_POLICY_NAME, -} from '../../store/constants'; +} from '../../constants'; import { findFirstError } from '../../services/find_errors'; import { NodeAttrsDetails } from './components/node_attrs_details'; import { PolicyJsonFlyout } from './components/policy_json_flyout'; diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js index 891d608b6dd66..d31aae042fe07 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js @@ -8,11 +8,7 @@ import React, { Component, Fragment } from 'react'; import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; -import { BASE_PATH } from '../../../../../common/constants'; -import { NoMatch } from '../no_match'; -import { getPolicyPath } from '../../../../services/navigation'; -import { flattenPanelTree } from '../../../../services/flatten_panel_tree'; -import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; + import { EuiBetaBadge, EuiButton, @@ -38,10 +34,17 @@ import { EuiPageBody, EuiPageContent, } from '@elastic/eui'; +import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; +import { getIndexListUri } from '../../../../../../index_management/public/services/navigation'; +import { BASE_PATH, UA_EDIT_CLICK } from '../../../../../common/constants'; +import { getPolicyPath } from '../../../../services/navigation'; +import { flattenPanelTree } from '../../../../services/flatten_panel_tree'; +import { trackUserAction } from '../../../../services'; +import { NoMatch } from '../no_match'; import { ConfirmDelete } from './confirm_delete'; import { AddPolicyToTemplateConfirmModal } from './add_policy_to_template_confirm_modal'; -import { getIndexListUri } from '../../../../../../index_management/public/services/navigation'; + const COLUMNS = { name: { label: i18n.translate('xpack.indexLifecycleMgmt.policyTable.headers.nameHeader', { @@ -176,6 +179,7 @@ export class PolicyTableUi extends Component { className="policyTable__link" data-test-subj="policyTablePolicyNameLink" href={getPolicyPath(value)} + onClick={() => trackUserAction(UA_EDIT_CLICK)} > {value} diff --git a/x-pack/plugins/index_lifecycle_management/public/services/api.js b/x-pack/plugins/index_lifecycle_management/public/services/api.js index a82cd3a0a7543..334f986b659d4 100644 --- a/x-pack/plugins/index_lifecycle_management/public/services/api.js +++ b/x-pack/plugins/index_lifecycle_management/public/services/api.js @@ -4,12 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ import chrome from 'ui/chrome'; +import { + UA_POLICY_DELETE, + UA_POLICY_ATTACH_INDEX, + UA_POLICY_ATTACH_INDEX_TEMPLATE, + UA_POLICY_DETACH_INDEX, + UA_INDEX_RETRY_STEP, +} from '../../common/constants'; +import { trackUserAction } from './user_action'; let httpClient; export const setHttpClient = (client) => { httpClient = client; }; -const getHttpClient = () => { +export const getHttpClient = () => { return httpClient; }; const apiPrefix = chrome.addBasePath('/api/index_lifecycle_management'); @@ -44,6 +52,8 @@ export async function loadPolicies(withIndices, httpClient = getHttpClient()) { export async function deletePolicy(policyName, httpClient = getHttpClient()) { const response = await httpClient.delete(`${apiPrefix}/policies/${encodeURIComponent(policyName)}`); + // Only track successful actions. + trackUserAction(UA_POLICY_DELETE, httpClient); return response.data; } @@ -52,7 +62,6 @@ export async function saveLifecycle(lifecycle, httpClient = getHttpClient()) { return response.data; } - export async function getAffectedIndices(indexTemplateName, policyName, httpClient = getHttpClient()) { const path = policyName ? `${apiPrefix}/indices/affected/${indexTemplateName}/${encodeURIComponent(policyName)}` @@ -60,19 +69,31 @@ export async function getAffectedIndices(indexTemplateName, policyName, httpClie const response = await httpClient.get(path); return response.data; } + export const retryLifecycleForIndex = async (indexNames, httpClient = getHttpClient()) => { const response = await httpClient.post(`${apiPrefix}/index/retry`, { indexNames }); + // Only track successful actions. + trackUserAction(UA_INDEX_RETRY_STEP, httpClient); return response.data; }; + export const removeLifecycleForIndex = async (indexNames, httpClient = getHttpClient()) => { const response = await httpClient.post(`${apiPrefix}/index/remove`, { indexNames }); + // Only track successful actions. + trackUserAction(UA_POLICY_DETACH_INDEX, httpClient); return response.data; }; + export const addLifecyclePolicyToIndex = async (body, httpClient = getHttpClient()) => { const response = await httpClient.post(`${apiPrefix}/index/add`, body); + // Only track successful actions. + trackUserAction(UA_POLICY_ATTACH_INDEX, httpClient); return response.data; }; + export const addLifecyclePolicyToTemplate = async (body, httpClient = getHttpClient()) => { const response = await httpClient.post(`${apiPrefix}/template`, body); + // Only track successful actions. + trackUserAction(UA_POLICY_ATTACH_INDEX_TEMPLATE, httpClient); return response.data; }; diff --git a/x-pack/plugins/index_lifecycle_management/public/services/index.js b/x-pack/plugins/index_lifecycle_management/public/services/index.js index a82b581309d29..d1160c4af8dbf 100644 --- a/x-pack/plugins/index_lifecycle_management/public/services/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/services/index.js @@ -6,3 +6,4 @@ export { filterItems } from './filter_items'; export { sortTable } from './sort_table'; +export { trackUserAction, getUserActionsForPhases } from './user_action'; diff --git a/x-pack/plugins/index_lifecycle_management/public/services/user_action.js b/x-pack/plugins/index_lifecycle_management/public/services/user_action.js new file mode 100644 index 0000000000000..d45b2f1ce4940 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/services/user_action.js @@ -0,0 +1,75 @@ +/* + * 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 { get } from 'lodash'; + +import { createUserActionUri } from '../../../../common/user_action'; + +import { + UA_APP_NAME, + UA_CONFIG_COLD_PHASE, + UA_CONFIG_WARM_PHASE, + UA_CONFIG_SET_PRIORITY, + UA_CONFIG_FREEZE_INDEX, +} from '../../common/constants'; + +import { + PHASE_HOT, + PHASE_WARM, + PHASE_COLD, + PHASE_INDEX_PRIORITY, +} from '../constants'; + +import { + defaultColdPhase, + defaultWarmPhase, + defaultHotPhase, +} from '../store/defaults'; + +import { getHttpClient } from './api'; + +export function trackUserAction(actionType, httpClient = getHttpClient()) { + const userActionUri = createUserActionUri(UA_APP_NAME, actionType); + httpClient.post(userActionUri); +} + +export function getUserActionsForPhases(phases) { + const possibleUserActions = [{ + action: UA_CONFIG_COLD_PHASE, + isExecuted: () => Boolean(phases[PHASE_COLD]), + }, { + action: UA_CONFIG_WARM_PHASE, + isExecuted: () => Boolean(phases[PHASE_WARM]), + }, { + action: UA_CONFIG_SET_PRIORITY, + isExecuted: () => { + const phaseToDefaultIndexPriorityMap = { + [PHASE_HOT]: defaultHotPhase[PHASE_INDEX_PRIORITY], + [PHASE_WARM]: defaultWarmPhase[PHASE_INDEX_PRIORITY], + [PHASE_COLD]: defaultColdPhase[PHASE_INDEX_PRIORITY], + }; + + // We only care about whether the user has interacted with the priority of *any* phase at all. + return [ PHASE_HOT, PHASE_WARM, PHASE_COLD ].some(phase => { + // If the priority is different than the default, we'll consider it a user interaction, + // even if the user has set it to undefined. + return phases[phase] && get(phases[phase], 'actions.set_priority.priority') !== phaseToDefaultIndexPriorityMap[phase]; + }); + }, + }, { + action: UA_CONFIG_FREEZE_INDEX, + isExecuted: () => phases[PHASE_COLD] && get(phases[PHASE_COLD], 'actions.freeze'), + }]; + + const executedUserActions = possibleUserActions.reduce((executed, { action, isExecuted }) => { + if (isExecuted()) { + executed.push(action); + } + return executed; + }, []); + + return executedUserActions; +} diff --git a/x-pack/plugins/index_lifecycle_management/public/services/user_action.test.js b/x-pack/plugins/index_lifecycle_management/public/services/user_action.test.js new file mode 100644 index 0000000000000..a66a9140d9a67 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/services/user_action.test.js @@ -0,0 +1,74 @@ +/* + * 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 { + UA_CONFIG_COLD_PHASE, + UA_CONFIG_WARM_PHASE, + UA_CONFIG_SET_PRIORITY, + UA_CONFIG_FREEZE_INDEX, +} from '../../common/constants'; + +import { + defaultColdPhase, + defaultWarmPhase, +} from '../store/defaults'; + +import { + PHASE_INDEX_PRIORITY, +} from '../constants'; + +import { getUserActionsForPhases } from './user_action'; + +describe('getUserActionsForPhases', () => { + test('gets cold phase', () => { + expect(getUserActionsForPhases({ + cold: { + actions: { + set_priority: { + priority: defaultColdPhase[PHASE_INDEX_PRIORITY], + }, + }, + }, + })).toEqual([UA_CONFIG_COLD_PHASE]); + }); + + test('gets warm phase', () => { + expect(getUserActionsForPhases({ + warm: { + actions: { + set_priority: { + priority: defaultWarmPhase[PHASE_INDEX_PRIORITY], + }, + }, + }, + })).toEqual([UA_CONFIG_WARM_PHASE]); + }); + + test(`gets index priority if it's different than the default value`, () => { + expect(getUserActionsForPhases({ + warm: { + actions: { + set_priority: { + priority: defaultWarmPhase[PHASE_INDEX_PRIORITY] + 1, + }, + }, + }, + })).toEqual([UA_CONFIG_WARM_PHASE, UA_CONFIG_SET_PRIORITY]); + }); + + test('gets freeze index', () => { + expect(getUserActionsForPhases({ + cold: { + actions: { + freeze: {}, + set_priority: { + priority: defaultColdPhase[PHASE_INDEX_PRIORITY], + }, + }, + }, + })).toEqual([UA_CONFIG_COLD_PHASE, UA_CONFIG_FREEZE_INDEX]); + }); +}); diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js index 9dcd1249de71c..c7de1ba2e4ce4 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js @@ -5,9 +5,15 @@ */ import { i18n } from '@kbn/i18n'; import { toastNotifications } from 'ui/notify'; + +import { + UA_POLICY_CREATE, + UA_POLICY_UPDATE, +} from '../../../common/constants'; + import { showApiError } from '../../services/api_errors'; import { saveLifecycle as saveLifecycleApi } from '../../services/api'; - +import { trackUserAction, getUserActionsForPhases } from '../../services'; export const saveLifecyclePolicy = (lifecycle, isNew) => async () => { try { @@ -23,6 +29,11 @@ export const saveLifecyclePolicy = (lifecycle, isNew) => async () => { showApiError(err, title); return false; } + + const userActions = getUserActionsForPhases(lifecycle.phases); + userActions.push(isNew ? UA_POLICY_CREATE : UA_POLICY_UPDATE); + trackUserAction(userActions.join(',')); + const message = i18n.translate('xpack.indexLifecycleMgmt.editPolicy.successfulSaveMessage', { defaultMessage: '{verb} lifecycle policy "{lifecycleName}"', diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js index a2a526e44298e..bb1f63c61cb23 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { createAction } from 'redux-actions'; import { showApiError } from '../../services/api_errors'; import { loadNodes, loadNodeDetails } from '../../services/api'; -import { SET_SELECTED_NODE_ATTRS } from '../constants'; +import { SET_SELECTED_NODE_ATTRS } from '../../constants'; export const setSelectedNodeAttrs = createAction(SET_SELECTED_NODE_ATTRS); export const setSelectedPrimaryShardCount = createAction( diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js index fb2384855d92c..c089dfa7e7520 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { showApiError } from '../../services/api_errors'; import { createAction } from 'redux-actions'; import { loadPolicies } from '../../services/api'; -import { SET_PHASE_DATA } from '../constants'; +import { SET_PHASE_DATA } from '../../constants'; export const fetchedPolicies = createAction('FETCHED_POLICIES'); export const setSelectedPolicy = createAction('SET_SELECTED_POLICY'); export const unsetSelectedPolicy = createAction('UNSET_SELECTED_POLICY'); diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js index 0a4f4e2206d65..0ff523a43867c 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js @@ -12,7 +12,7 @@ import { PHASE_ROLLOVER_ALIAS, PHASE_FREEZE_ENABLED, PHASE_INDEX_PRIORITY, -} from '../constants'; +} from '../../constants'; export const defaultColdPhase = { [PHASE_ENABLED]: false, diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js index c449ba073fd24..901ac4f6a4668 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js @@ -9,7 +9,7 @@ import { PHASE_ROLLOVER_MINIMUM_AGE, PHASE_ROLLOVER_MINIMUM_AGE_UNITS, PHASE_ROLLOVER_ALIAS, -} from '../constants'; +} from '../../constants'; export const defaultDeletePhase = { [PHASE_ENABLED]: false, diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js index 43ffc1b565e5b..ba88979435256 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js @@ -12,7 +12,7 @@ import { PHASE_ROLLOVER_MAX_DOCUMENTS, PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS, PHASE_INDEX_PRIORITY -} from '../constants'; +} from '../../constants'; export const defaultHotPhase = { [PHASE_ENABLED]: true, diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js index 8e55b5c72c4f0..7e6dcd41f4871 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js @@ -16,7 +16,7 @@ import { PHASE_SHRINK_ENABLED, WARM_PHASE_ON_ROLLOVER, PHASE_INDEX_PRIORITY -} from '../constants'; +} from '../../constants'; export const defaultWarmPhase = { [PHASE_ENABLED]: false, diff --git a/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js index 27b5304fec1fa..8fc0bc1b73766 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js @@ -27,7 +27,7 @@ import { PHASE_COLD, PHASE_DELETE, PHASE_ATTRIBUTES_THAT_ARE_NUMBERS, -} from '../constants'; +} from '../../constants'; import { defaultColdPhase, diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js index a25299d54675a..b89e74781b344 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js @@ -25,7 +25,7 @@ import { WARM_PHASE_ON_ROLLOVER, PHASE_INDEX_PRIORITY, PHASE_ROLLOVER_MAX_DOCUMENTS -} from '../constants'; +} from '../../constants'; import { getPhase, getPhases, diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js index 30649e8a62042..31af91c122019 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js @@ -32,7 +32,7 @@ import { PHASE_FREEZE_ENABLED, PHASE_INDEX_PRIORITY, PHASE_ROLLOVER_MAX_DOCUMENTS -} from '../constants'; +} from '../../constants'; import { defaultEmptyDeletePhase, defaultEmptyColdPhase, diff --git a/x-pack/plugins/index_lifecycle_management/server/usage/collector.js b/x-pack/plugins/index_lifecycle_management/server/usage/collector.js new file mode 100644 index 0000000000000..4fb067a2eaa91 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/usage/collector.js @@ -0,0 +1,25 @@ +/* + * 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 { fetchUserActions } from '../../../../server/lib/user_action'; +import { UA_APP_NAME, USER_ACTIONS } from '../../common/constants'; + +const INDEX_LIFECYCLE_MANAGEMENT_USAGE_TYPE = 'index_lifecycle_management'; + +export function registerIndexLifecycleManagementUsageCollector(server) { + const collector = server.usage.collectorSet.makeUsageCollector({ + type: INDEX_LIFECYCLE_MANAGEMENT_USAGE_TYPE, + fetch: async () => { + const userActions = await fetchUserActions(server, UA_APP_NAME, USER_ACTIONS); + + return { + user_actions: userActions, + }; + }, + }); + + server.usage.collectorSet.register(collector); +} diff --git a/x-pack/plugins/index_lifecycle_management/server/usage/index.js b/x-pack/plugins/index_lifecycle_management/server/usage/index.js new file mode 100644 index 0000000000000..f0fec917cd56e --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/usage/index.js @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { registerIndexLifecycleManagementUsageCollector } from './collector'; diff --git a/x-pack/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/plugins/index_management/__jest__/components/index_table.test.js index 9e795c38979e9..fa7f82be5a2d7 100644 --- a/x-pack/plugins/index_management/__jest__/components/index_table.test.js +++ b/x-pack/plugins/index_management/__jest__/components/index_table.test.js @@ -6,7 +6,7 @@ import React from 'react'; import { MemoryRouter } from 'react-router-dom'; -import { App } from '../../public/app'; +import { AppWithoutRouter } from '../../public/app'; import { Provider } from 'react-redux'; import { loadIndicesSuccess } from '../../public/store/actions'; import { indexManagementStore } from '../../public/store'; @@ -123,7 +123,7 @@ describe('index table', () => { component = ( - + ); diff --git a/x-pack/plugins/index_management/common/constants/user_action.js b/x-pack/plugins/index_management/common/constants/user_action.js index 9f491e4918c4d..47eda91edfed7 100644 --- a/x-pack/plugins/index_management/common/constants/user_action.js +++ b/x-pack/plugins/index_management/common/constants/user_action.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export const UA_APP_NAME = 'index-management'; +export const UA_APP_NAME = 'index_management'; export const UA_APP_LOAD = 'app_load'; export const UA_UPDATE_SETTINGS = 'update_settings'; diff --git a/x-pack/plugins/index_management/public/app.js b/x-pack/plugins/index_management/public/app.js index 5446e20f18523..b7302f4836290 100644 --- a/x-pack/plugins/index_management/public/app.js +++ b/x-pack/plugins/index_management/public/app.js @@ -4,26 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Component } from 'react'; -import { Switch, Route, Redirect } from 'react-router-dom'; +import React, { useEffect } from 'react'; +import { HashRouter, Switch, Route, Redirect } from 'react-router-dom'; import { BASE_PATH, UA_APP_LOAD } from '../common/constants'; import { IndexList } from './sections/index_list'; import { trackUserAction } from './services'; -export class App extends Component { - componentWillMount() { - trackUserAction(UA_APP_LOAD); - } +export const App = () => { + useEffect(() => trackUserAction(UA_APP_LOAD), []); - render() { - return ( -
    - - - - - -
    - ); - } -} + return ( + + + + ); +}; + +// Exoprt this so we can test it with a different router. +export const AppWithoutRouter = () => ( + + + + + +); diff --git a/x-pack/plugins/index_management/public/register_routes.js b/x-pack/plugins/index_management/public/register_routes.js index a926d64d32743..41787befd5c23 100644 --- a/x-pack/plugins/index_management/public/register_routes.js +++ b/x-pack/plugins/index_management/public/register_routes.js @@ -7,7 +7,6 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Provider } from 'react-redux'; -import { HashRouter } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { setHttpClient } from './services/api'; import { setUrlService } from './services/navigation'; @@ -28,9 +27,7 @@ const renderReact = async (elem) => { render( - - - + , elem diff --git a/x-pack/plugins/rollup/public/crud_app/app.js b/x-pack/plugins/rollup/public/crud_app/app.js index 11ac412104db8..2e6994a01d3e7 100644 --- a/x-pack/plugins/rollup/public/crud_app/app.js +++ b/x-pack/plugins/rollup/public/crud_app/app.js @@ -6,14 +6,14 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { Switch, Route, Redirect } from 'react-router-dom'; +import { HashRouter, Switch, Route, Redirect } from 'react-router-dom'; import { UA_APP_LOAD } from '../../common'; import { CRUD_APP_BASE_PATH } from './constants'; import { registerRouter, setUserHasLeftApp, trackUserAction } from './services'; import { JobList, JobCreate } from './sections'; -export class App extends Component { +class ShareRouter extends Component { static contextTypes = { router: PropTypes.shape({ history: PropTypes.shape({ @@ -34,7 +34,13 @@ export class App extends Component { registerRouter(router); } - componentWillMount() { + render() { + return this.props.children; + } +} + +export class App extends Component { // eslint-disable-line react/no-multi-comp + componentDidMount() { trackUserAction(UA_APP_LOAD); } @@ -45,11 +51,15 @@ export class App extends Component { render() { return ( - - - - - + + + + + + + + + ); } } diff --git a/x-pack/plugins/rollup/public/crud_app/index.js b/x-pack/plugins/rollup/public/crud_app/index.js index b43592c8e2284..28e9973d2151b 100644 --- a/x-pack/plugins/rollup/public/crud_app/index.js +++ b/x-pack/plugins/rollup/public/crud_app/index.js @@ -8,7 +8,6 @@ import React from 'react'; import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; import { render, unmountComponentAtNode } from 'react-dom'; import { Provider } from 'react-redux'; -import { HashRouter } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { I18nContext } from 'ui/i18n'; import { management } from 'ui/management'; @@ -33,9 +32,7 @@ const renderReact = async (elem) => { render( - - - + , elem diff --git a/x-pack/plugins/rollup/public/crud_app/services/track_user_action.js b/x-pack/plugins/rollup/public/crud_app/services/track_user_action.js index c2d588dd4d3a0..1db7fe69095ea 100644 --- a/x-pack/plugins/rollup/public/crud_app/services/track_user_action.js +++ b/x-pack/plugins/rollup/public/crud_app/services/track_user_action.js @@ -13,8 +13,16 @@ export function trackUserAction(actionType) { getHttp().post(userActionUri); } +/** + * Transparently return provided request Promise, while allowing us to track + * a successful completion of the request. + */ export function trackUserRequest(request, actionType) { // Only track successful actions. - request.then(() => trackUserAction(actionType)); - return request; + return request.then(response => { + trackUserAction(actionType); + // We return the response immediately without waiting for the tracking request to resolve, + // to avoid adding additional latency. + return response; + }); } From 3b020f055b161561c4b70495c31904cb1ed52703 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 27 Mar 2019 00:41:24 +0000 Subject: [PATCH 45/96] docs(NA): missing header for unit testing. (#33895) --- docs/development/core-development.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/development/core-development.asciidoc b/docs/development/core-development.asciidoc index ed04a6f12eae9..447a4c6d2601b 100644 --- a/docs/development/core-development.asciidoc +++ b/docs/development/core-development.asciidoc @@ -5,6 +5,7 @@ * <> * <> * <> +* <> * <> include::core/development-basepath.asciidoc[] From 33fa8c0c6b4a37b94d418e8604f80900c12805f8 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 26 Mar 2019 20:18:14 -0700 Subject: [PATCH 46/96] Add eslint rule for checking React Hooks best practices. (#33901) * Rename Console's useResizeChecker to applyResizeCheckerToEditors, to bypass greedy react-hooks lint rule. --- package.json | 1 + packages/eslint-config-kibana/.eslintrc.js | 3 +++ packages/eslint-config-kibana/package.json | 3 ++- .../console/public/src/controllers/sense_controller.js | 4 ++-- .../console/public/src/directives/sense_help_example.js | 4 ++-- .../console/public/src/directives/sense_history_viewer.js | 4 ++-- .../core_plugins/console/public/src/sense_editor_resize.js | 2 +- yarn.lock | 5 +++++ 8 files changed, 18 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 3d3a64a56e671..5abfcdd651a83 100644 --- a/package.json +++ b/package.json @@ -346,6 +346,7 @@ "eslint-plugin-prefer-object-spread": "^1.2.1", "eslint-plugin-prettier": "^3.0.1", "eslint-plugin-react": "^7.12.4", + "eslint-plugin-react-hooks": "^1.6.0", "faker": "1.1.0", "fetch-mock": "7.3.0", "geckodriver": "1.12.2", diff --git a/packages/eslint-config-kibana/.eslintrc.js b/packages/eslint-config-kibana/.eslintrc.js index 9906f9cf8dfe6..0b509d81c5795 100644 --- a/packages/eslint-config-kibana/.eslintrc.js +++ b/packages/eslint-config-kibana/.eslintrc.js @@ -10,6 +10,7 @@ module.exports = { 'mocha', 'babel', 'react', + 'react-hooks', 'import', 'no-unsanitized', 'prefer-object-spread', @@ -127,6 +128,8 @@ module.exports = { arrow: true, }], 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], + 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks + 'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies 'jsx-a11y/accessible-emoji': 'error', 'jsx-a11y/alt-text': 'error', 'jsx-a11y/anchor-has-content': 'error', diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json index c4a5a99e4c976..4be75ca2bcbe5 100644 --- a/packages/eslint-config-kibana/package.json +++ b/packages/eslint-config-kibana/package.json @@ -24,6 +24,7 @@ "eslint-plugin-mocha": "^5.3.0", "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", - "eslint-plugin-react": "^7.12.4" + "eslint-plugin-react": "^7.12.4", + "eslint-plugin-react-hooks": "^1.6.0" } } diff --git a/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js b/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js index 4d3757be9a6ac..58fe1df256adc 100644 --- a/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js +++ b/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js @@ -17,7 +17,7 @@ * under the License. */ import 'ui/doc_title'; -import { useResizeChecker } from '../sense_editor_resize'; +import { applyResizeCheckerToEditors } from '../sense_editor_resize'; import $ from 'jquery'; import { initializeInput } from '../input'; import { initializeOutput } from '../output'; @@ -30,7 +30,7 @@ const module = require('ui/modules').get('app/sense'); module.run(function (Private, $rootScope) { module.setupResizeCheckerForRootEditors = ($el, ...editors) => { - return useResizeChecker($rootScope, $el, ...editors); + return applyResizeCheckerToEditors($rootScope, $el, ...editors); }; }); diff --git a/src/legacy/core_plugins/console/public/src/directives/sense_help_example.js b/src/legacy/core_plugins/console/public/src/directives/sense_help_example.js index 6a7cbff4df3d7..d4e4632a45dfb 100644 --- a/src/legacy/core_plugins/console/public/src/directives/sense_help_example.js +++ b/src/legacy/core_plugins/console/public/src/directives/sense_help_example.js @@ -19,7 +19,7 @@ const SenseEditor = require('../sense_editor/editor'); const exampleText = require('raw-loader!./helpExample.txt').trim(); -import { useResizeChecker } from '../sense_editor_resize'; +import { applyResizeCheckerToEditors } from '../sense_editor_resize'; require('ui/modules') .get('app/sense') @@ -29,7 +29,7 @@ require('ui/modules') link: function ($scope, $el) { $el.text(exampleText); $scope.editor = new SenseEditor($el); - useResizeChecker($scope, $el, $scope.editor); + applyResizeCheckerToEditors($scope, $el, $scope.editor); $scope.editor.setReadOnly(true); $scope.editor.$blockScrolling = Infinity; diff --git a/src/legacy/core_plugins/console/public/src/directives/sense_history_viewer.js b/src/legacy/core_plugins/console/public/src/directives/sense_history_viewer.js index 9502a10f0a362..d7ad736335f52 100644 --- a/src/legacy/core_plugins/console/public/src/directives/sense_history_viewer.js +++ b/src/legacy/core_plugins/console/public/src/directives/sense_history_viewer.js @@ -19,7 +19,7 @@ const SenseEditor = require('../sense_editor/editor'); -import { useResizeChecker } from '../sense_editor_resize'; +import { applyResizeCheckerToEditors } from '../sense_editor_resize'; require('ui/modules') .get('app/sense') @@ -33,7 +33,7 @@ require('ui/modules') const viewer = new SenseEditor($el); viewer.setReadOnly(true); viewer.renderer.setShowPrintMargin(false); - useResizeChecker($scope, $el, viewer); + applyResizeCheckerToEditors($scope, $el, viewer); require('../settings').applyCurrentSettings(viewer); $scope.$watch('req', function (req) { diff --git a/src/legacy/core_plugins/console/public/src/sense_editor_resize.js b/src/legacy/core_plugins/console/public/src/sense_editor_resize.js index eff840254a864..6b950a394db1b 100644 --- a/src/legacy/core_plugins/console/public/src/sense_editor_resize.js +++ b/src/legacy/core_plugins/console/public/src/sense_editor_resize.js @@ -19,7 +19,7 @@ import { ResizeChecker } from 'ui/resize_checker'; -export function useResizeChecker($scope, $el, ...editors) { +export function applyResizeCheckerToEditors($scope, $el, ...editors) { const checker = new ResizeChecker($el); checker.on('resize', () => editors.forEach(e => e.resize())); $scope.$on('$destroy', () => checker.destroy()); diff --git a/yarn.lock b/yarn.lock index 18dccaaa691cf..848c82f95a4ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8609,6 +8609,11 @@ eslint-plugin-prettier@^3.0.1: dependencies: prettier-linter-helpers "^1.0.0" +eslint-plugin-react-hooks@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.6.0.tgz#348efcda8fb426399ac7b8609607c7b4025a6f5f" + integrity sha512-lHBVRIaz5ibnIgNG07JNiAuBUeKhEf8l4etNx5vfAEwqQ5tcuK3jV9yjmopPgQDagQb7HwIuQVsE3IVcGrRnag== + eslint-plugin-react@^7.12.4: version "7.12.4" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz#b1ecf26479d61aee650da612e425c53a99f48c8c" From 412c9d843e5534137aa0b4152edac1146f5fe679 Mon Sep 17 00:00:00 2001 From: Vitali Haradkou Date: Wed, 27 Mar 2019 13:35:10 +0300 Subject: [PATCH 47/96] [TSVB] markdown variables (#33324) * improve test coverage for TSVB markdown * add new tests for change label, variable and rendering markdown table --- .../apps/visualize/_tsvb_markdown.ts | 65 +++++++++++++++++-- .../page_objects/visual_builder_page.ts | 30 ++++++++- test/functional/services/browser.js | 14 ++-- test/functional/services/remote/webdriver.ts | 1 - 4 files changed, 96 insertions(+), 14 deletions(-) diff --git a/test/functional/apps/visualize/_tsvb_markdown.ts b/test/functional/apps/visualize/_tsvb_markdown.ts index 3e62eba78a528..47a5e68e68f39 100644 --- a/test/functional/apps/visualize/_tsvb_markdown.ts +++ b/test/functional/apps/visualize/_tsvb_markdown.ts @@ -22,11 +22,20 @@ import { FtrProviderContext } from '../../ftr_provider_context'; // tslint:disable-next-line:no-default-export export default function({ getPageObjects }: FtrProviderContext) { - const { visualBuilder, timePicker } = getPageObjects([ - 'visualBuilder', - 'timePicker', - 'visualize', - ]); + const { visualBuilder, timePicker } = getPageObjects(['visualBuilder', 'timePicker']); + + async function cleanupMarkdownData(variableName: 'variable' | 'label', checkedValue: string) { + await visualBuilder.markdownSwitchSubTab('data'); + await visualBuilder.setMarkdownDataVariable('', variableName); + + await visualBuilder.markdownSwitchSubTab('markdown'); + const rerenderedTable = await visualBuilder.getMarkdownTableVariables(); + rerenderedTable.forEach(row => { + variableName === 'label' + ? expect(row.key).to.include.string(checkedValue) + : expect(row.key).to.not.include.string(checkedValue); + }); + } describe('visual builder', function describeIndexTests() { describe('markdown', () => { @@ -71,6 +80,52 @@ export default function({ getPageObjects }: FtrProviderContext) { const markdownText = await visualBuilder.getMarkdownText(); expect(markdownText).to.be(expectedRenderer); }); + + it('should change label name', async () => { + const BASE_LABEL = 'count'; + const LABEL = 'label'; + await visualBuilder.markdownSwitchSubTab('data'); + + await visualBuilder.setMarkdownDataVariable(LABEL, LABEL); + + await visualBuilder.markdownSwitchSubTab('markdown'); + const table = await visualBuilder.getMarkdownTableVariables(); + table.forEach(row => { + expect(row.key).to.contain(LABEL); + }); + await cleanupMarkdownData(LABEL, BASE_LABEL); + }); + + it('should change variable name', async () => { + const VARIABLE = 'variable'; + await visualBuilder.markdownSwitchSubTab('data'); + await visualBuilder.setMarkdownDataVariable(VARIABLE, VARIABLE); + await visualBuilder.markdownSwitchSubTab('markdown'); + const table = await visualBuilder.getMarkdownTableVariables(); + + table.forEach((row, index) => { + // exception: last index for variable is always: {{count.label}} + index === table.length - 1 + ? expect(row.key).to.not.include.string(VARIABLE) + : expect(row.key).to.include.string(VARIABLE); + }); + + await cleanupMarkdownData(VARIABLE, VARIABLE); + }); + + it('should render markdown table', async () => { + const TABLE = + '| raw | formatted |\n|-|-|\n| {{count.last.raw}} | {{count.last.formatted}} |'; + const DATA = '46'; + + await visualBuilder.enterMarkdown(TABLE); + const text = await visualBuilder.getMarkdownText(); + const tableValues = text.split('\n').map(row => row.split(' '))[1]; // [46, 46] + + tableValues.forEach(value => { + expect(value).to.be.equal(DATA); + }); + }); }); }); } diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index bd2f219486bf5..4224af0af8e49 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -83,7 +83,7 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro await input.pressKeys(browser.keys.BACK_SPACE); // Delete all content } - public async getMarkdownText() { + public async getMarkdownText(): Promise { const el = await find.byCssSelector('.tvbEditorVisualization'); const text = await el.getVisibleText(); return text; @@ -156,6 +156,34 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro await element.click(); } + /** + * setting label for markdown visualization + * + * @param {string} variableName + * @param type + * @memberof VisualBuilderPage + */ + public async setMarkdownDataVariable(variableName: string, type: 'variable' | 'label') { + const SELECTOR = type === 'label' ? '[placeholder="Label"]' : '[placeholder="Variable name"]'; + const prevRenderingCount = await PageObjects.visualize.getVisualizationRenderingCount(); + if (variableName) { + await find.setValue(SELECTOR, variableName); + } else { + const input = await find.byCssSelector(SELECTOR); + if (process.platform === 'darwin') { + // Mac workaround + for (let i = 0; i <= type.length; i++) { + await input.pressKeys(browser.keys.BACK_SPACE); + } + } else { + await input.pressKeys([browser.keys.CONTROL, 'a']); // Select all for everything else + await input.pressKeys(browser.keys.NULL); // Release modifier keys + await input.pressKeys(browser.keys.BACK_SPACE); // Delete all content + } + } + await PageObjects.visualize.waitForRenderingCount(prevRenderingCount + 1); + } + public async clickSeriesOption(nth = 0) { const el = await testSubjects.findAll('seriesOptions'); await el[nth].click(); diff --git a/test/functional/services/browser.js b/test/functional/services/browser.js index 7f7e26de888bd..55322b386e8f2 100644 --- a/test/functional/services/browser.js +++ b/test/functional/services/browser.js @@ -22,11 +22,11 @@ import { cloneDeep } from 'lodash'; import { modifyUrl } from '../../../src/core/utils'; import { WebElementWrapper } from './lib/web_element_wrapper'; + export async function BrowserProvider({ getService }) { const { driver, Key, LegacyActionSequence } = await getService('__webdriver__').init(); class BrowserService { - /** * Keyboard events */ @@ -121,8 +121,8 @@ export async function BrowserProvider({ getService }) { async dragAndDrop(from, to) { let _from; let _to; - const _fromOffset = (from.offset) ? { x: from.offset.x || 0, y: from.offset.y || 0 } : { x: 0, y: 0 }; - const _toOffset = (to.offset) ? { x: to.offset.x || 0, y: to.offset.y || 0 } : { x: 0, y: 0 }; + const _fromOffset = from.offset ? { x: from.offset.x || 0, y: from.offset.y || 0 } : { x: 0, y: 0 }; + const _toOffset = to.offset ? { x: to.offset.x || 0, y: to.offset.y || 0 } : { x: 0, y: 0 }; if (from.location instanceof WebElementWrapper) { _from = from.location._webElement; @@ -230,9 +230,9 @@ export async function BrowserProvider({ getService }) { * @return {Promise} */ async getLogsFor(...args) { - //The logs endpoint has not been defined in W3C Spec browsers other than Chrome don't have access to this endpoint. - //See: https://github.com/w3c/webdriver/issues/406 - //See: https://w3c.github.io/webdriver/#endpoints + // The logs endpoint has not been defined in W3C Spec browsers other than Chrome don't have access to this endpoint. + // See: https://github.com/w3c/webdriver/issues/406 + // See: https://w3c.github.io/webdriver/#endpoints if (driver.executor_.w3c === true) { return []; } else { @@ -358,5 +358,5 @@ export async function BrowserProvider({ getService }) { } } - return new BrowserService(); + return new BrowserService(); } diff --git a/test/functional/services/remote/webdriver.ts b/test/functional/services/remote/webdriver.ts index 0be87382c94a0..8bc4a2cb31db9 100644 --- a/test/functional/services/remote/webdriver.ts +++ b/test/functional/services/remote/webdriver.ts @@ -22,7 +22,6 @@ import { delay } from 'bluebird'; import chromeDriver from 'chromedriver'; // @ts-ignore types not available import geckoDriver from 'geckodriver'; - // @ts-ignore types for 4.0 not available yet import { Builder, By, Key, logging, until } from 'selenium-webdriver'; // @ts-ignore types not available From 0603f7a8dbc2632d64fce46f11f25ada3eade076 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Wed, 27 Mar 2019 11:05:12 +0000 Subject: [PATCH 48/96] [ML] Adds created_by field to auditbeat and APM data recognizer jobs (#33863) --- .../modules/apm_transaction/ml/high_mean_response_time.json | 3 +++ .../ml/docker_high_count_process_events_ecs.json | 1 + .../ml/docker_rare_process_activity_ecs.json | 1 + .../ml/hosts_high_count_process_events_ecs.json | 2 +- .../ml/hosts_rare_process_activity_ecs.json | 2 +- 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json index 9ae180c42068e..f6c230a6792fb 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json @@ -23,5 +23,8 @@ }, "model_plot_config": { "enabled": true + }, + "custom_settings": { + "created_by": "ml-module-apm-transaction" } } 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 b0df941c416b8..d8c970e179416 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 @@ -25,6 +25,7 @@ "time_format": "epoch_ms" }, "custom_settings": { + "created_by": "ml-module-auditbeat-process-docker", "custom_urls": [ { "url_name": "Process rate", 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 f04fc11716642..76e3c8026c631 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 @@ -25,6 +25,7 @@ "time_format": "epoch_ms" }, "custom_settings": { + "created_by": "ml-module-auditbeat-process-docker", "custom_urls": [ { "url_name": "Process explorer", 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 9ddfe9aa66b89..487bee5311878 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 @@ -24,7 +24,7 @@ "time_format": "epoch_ms" }, "custom_settings": { - "created_by": "ml-module-auditd-hosts", + "created_by": "ml-module-auditbeat-process-hosts", "custom_urls": [ { "url_name": "Process rate", 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 4c1549cc10ab0..9ba6859bfa166 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 @@ -25,7 +25,7 @@ "time_format": "epoch_ms" }, "custom_settings": { - "created_by": "ml-module-auditd-hosts", + "created_by": "ml-module-auditbeat-process-hosts", "custom_urls": [ { "url_name": "Process explorer", From d3ad8a4b0b45d597e322a13c7b9e02cd308aaa19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Wed, 27 Mar 2019 14:44:24 +0100 Subject: [PATCH 49/96] [CCR & Rollup] Update client integration tests (#33857) --- .../auto_follow_pattern_list.test.js | 25 ++- .../follower_indices_list.test.js | 39 ++--- .../__jest__/client_integration/home.test.js | 9 +- .../client_integration/test_helpers.js | 30 +--- .../client_integration/job_list.test.js | 143 ++++++++++++++++++ .../sections/job_list/job_table/job_table.js | 2 +- .../rollup/public/crud_app/store/index.js | 2 +- .../rollup/public/crud_app/store/store.js | 2 +- 8 files changed, 200 insertions(+), 52 deletions(-) create mode 100644 x-pack/plugins/rollup/__jest__/client_integration/job_list.test.js diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js index f9933cd60f1ca..502512ab0dd56 100644 --- a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js @@ -6,7 +6,7 @@ import sinon from 'sinon'; -import { initTestBed, mockAllHttpRequests, nextTick, getRandomString, findTestSubject } from './test_helpers'; +import { initTestBed, registerHttpRequestMockHelpers, nextTick, getRandomString, findTestSubject } from './test_helpers'; import { AutoFollowPatternList } from '../../public/app/sections/home/auto_follow_pattern_list'; import { getAutoFollowPatternClientMock } from '../../fixtures/auto_follow_pattern'; @@ -29,12 +29,25 @@ describe('', () => { let getUserActions; let tableCellsValues; let rows; - let updateHttpMockResponse; + let setLoadAutoFollowPatternsResponse; + let setDeleteAutoFollowPatternResponse; + let setAutoFollowStatsResponse; beforeEach(() => { server = sinon.fakeServer.create(); server.respondImmediately = true; - (updateHttpMockResponse = mockAllHttpRequests(server)); + + // Register helpers to mock Http Requests + ({ + setLoadAutoFollowPatternsResponse, + setDeleteAutoFollowPatternResponse, + setAutoFollowStatsResponse + } = registerHttpRequestMockHelpers(server)); + + // Set "default" mock responses by not providing any arguments + setLoadAutoFollowPatternsResponse(); + setDeleteAutoFollowPatternResponse(); + setAutoFollowStatsResponse(); }); describe('on component mount', () => { @@ -88,7 +101,7 @@ describe('', () => { let clickAutoFollowPatternAt; beforeEach(async () => { - updateHttpMockResponse('loadAutoFollowPatterns', { patterns: autoFollowPatterns }); + setLoadAutoFollowPatternsResponse({ patterns: autoFollowPatterns }); // Mount the component ({ @@ -179,7 +192,7 @@ describe('', () => { expect(rows.length).toBe(2); // We wil delete the *first* auto-follow pattern in the table - updateHttpMockResponse('deleteAutoFollowPattern', { itemsDeleted: [autoFollowPattern1.name] }); + setDeleteAutoFollowPatternResponse({ itemsDeleted: [autoFollowPattern1.name] }); selectAutoFollowPatternAt(0); clickBulkDeleteButton(); @@ -301,7 +314,7 @@ describe('', () => { leaderIndex: `${autoFollowPattern2.name}:my-leader-test`, autoFollowException: { type: 'exception', reason: message } }]; - updateHttpMockResponse('autoFollowStats', { recentAutoFollowErrors }); + setAutoFollowStatsResponse({ recentAutoFollowErrors }); clickAutoFollowPatternAt(0); expect(exists('ccrAutoFollowPatternDetailErrors')).toBe(false); diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js index eb30e796cbaea..4b48b37a0c193 100644 --- a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js @@ -6,7 +6,7 @@ import sinon from 'sinon'; -import { initTestBed, mockAllHttpRequests, nextTick, getRandomString } from './test_helpers'; +import { initTestBed, registerHttpRequestMockHelpers, nextTick, getRandomString } from './test_helpers'; import { FollowerIndicesList } from '../../public/app/sections/home/follower_indices_list'; import { getFollowerIndexMock } from '../../fixtures/follower_index'; @@ -28,12 +28,17 @@ describe('', () => { let getMetadataFromEuiTable; let getUserActions; let tableCellsValues; - let updateHttpMockResponse; + let setLoadFollowerIndicesResponse; beforeEach(() => { server = sinon.fakeServer.create(); server.respondImmediately = true; - (updateHttpMockResponse = mockAllHttpRequests(server)); + + // Register helpers to mock Http Requests + ({ setLoadFollowerIndicesResponse } = registerHttpRequestMockHelpers(server)); + + // Set "default" mock responses by not providing any arguments + setLoadFollowerIndicesResponse(); }); describe('on component mount', () => { @@ -79,7 +84,7 @@ describe('', () => { let clickFollowerIndexAt; beforeEach(async () => { - updateHttpMockResponse('loadFollowerIndices', { indices: followerIndices }); + setLoadFollowerIndicesResponse({ indices: followerIndices }); // Mount the component ({ @@ -289,19 +294,19 @@ describe('', () => { test('should set the correct follower index settings values', () => { const mapSettingsToFollowerIndexProp = { - 'Status': 'status', - 'RemoteCluster': 'remoteCluster', - 'LeaderIndex': 'leaderIndex', - 'MaxReadReqOpCount': 'maxReadRequestOperationCount', - 'MaxOutstandingReadReq': 'maxOutstandingReadRequests', - 'MaxReadReqSize': 'maxReadRequestSize', - 'MaxWriteReqOpCount': 'maxWriteRequestOperationCount', - 'MaxWriteReqSize': 'maxWriteRequestSize', - 'MaxOutstandingWriteReq': 'maxOutstandingWriteRequests', - 'MaxWriteBufferCount': 'maxWriteBufferCount', - 'MaxWriteBufferSize': 'maxWriteBufferSize', - 'MaxRetryDelay': 'maxRetryDelay', - 'ReadPollTimeout': 'readPollTimeout' + Status: 'status', + RemoteCluster: 'remoteCluster', + LeaderIndex: 'leaderIndex', + MaxReadReqOpCount: 'maxReadRequestOperationCount', + MaxOutstandingReadReq: 'maxOutstandingReadRequests', + MaxReadReqSize: 'maxReadRequestSize', + MaxWriteReqOpCount: 'maxWriteRequestOperationCount', + MaxWriteReqSize: 'maxWriteRequestSize', + MaxOutstandingWriteReq: 'maxOutstandingWriteRequests', + MaxWriteBufferCount: 'maxWriteBufferCount', + MaxWriteBufferSize: 'maxWriteBufferSize', + MaxRetryDelay: 'maxRetryDelay', + ReadPollTimeout: 'readPollTimeout' }; clickFollowerIndexAt(0); diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js index 5d09018a2bbd6..e63a4653d1896 100644 --- a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js @@ -6,7 +6,7 @@ import sinon from 'sinon'; -import { initTestBed, mockAllHttpRequests, nextTick } from './test_helpers'; +import { initTestBed, registerHttpRequestMockHelpers, nextTick } from './test_helpers'; import { CrossClusterReplicationHome } from '../../public/app/sections/home/home'; import { BASE_PATH } from '../../common/constants'; import routing from '../../public/app/services/routing'; @@ -38,7 +38,12 @@ describe('', () => { beforeEach(() => { server = sinon.fakeServer.create(); server.respondImmediately = true; - mockAllHttpRequests(server); + + // Register helpers to mock Http Requests + const { setLoadFollowerIndicesResponse } = registerHttpRequestMockHelpers(server); + + // Set "default" mock responses by not providing any arguments + setLoadFollowerIndicesResponse(); }); describe('on component mount', () => { diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js index 2bd747977c111..ba0cdb0a67169 100644 --- a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js @@ -137,7 +137,7 @@ export const initTestBed = (component, props = {}, options) => { }; }; -export const mockAllHttpRequests = server => { +export const registerHttpRequestMockHelpers = server => { const mockResponse = (defaultResponse, response) => ([ 200, { 'Content-Type': 'application/json' }, @@ -185,28 +185,10 @@ export const mockAllHttpRequests = server => { ); }; - /** - * Set all http request to their default response - */ - setLoadFollowerIndicesResponse(); - setLoadAutoFollowPatternsResponse(); - setAutoFollowStatsResponse(); - - /** - * Return a method to override any of the http reques - */ - return (request, response) => { - const mapRequestToHelper = { - 'loadFollowerIndices': setLoadFollowerIndicesResponse, - 'loadAutoFollowPatterns': setLoadAutoFollowPatternsResponse, - 'deleteAutoFollowPattern': setDeleteAutoFollowPatternResponse, - 'autoFollowStats': setAutoFollowStatsResponse, - }; - - if (!mapRequestToHelper[request]) { - throw new Error(`Did not find a helper to set http response for request ${request}`); - } - - return mapRequestToHelper[request](response); + return { + setLoadFollowerIndicesResponse, + setLoadAutoFollowPatternsResponse, + setDeleteAutoFollowPatternResponse, + setAutoFollowStatsResponse, }; }; diff --git a/x-pack/plugins/rollup/__jest__/client_integration/job_list.test.js b/x-pack/plugins/rollup/__jest__/client_integration/job_list.test.js new file mode 100644 index 0000000000000..951e63147e435 --- /dev/null +++ b/x-pack/plugins/rollup/__jest__/client_integration/job_list.test.js @@ -0,0 +1,143 @@ +/* + * 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 sinon from 'sinon'; +import axios from 'axios'; + +import { registerTestBed, nextTick } from '../../../../test_utils'; +import { createRollupJobsStore } from '../../public/crud_app/store'; +import { setHttp, registerRouter, getRouter } from '../../public/crud_app/services'; +import { JobList } from '../../public/crud_app/sections/job_list'; + +// axios has a $http like interface so using it to simulate $http +setHttp(axios.create()); + +jest.mock('ui/chrome', () => ({ + addBasePath: (path) => path ? path : 'api/rollup', + breadcrumbs: { set: () => {} }, +})); + +jest.mock('../../public/crud_app/services', () => { + const services = require.requireActual('../../public/crud_app/services'); + return { + ...services, + getRouterLinkProps: (link) => ({ href: link }), + }; +}); + +const loadJobsMock = { + jobs: [{ + config: { + id: 'my-rollup-job', + index_pattern: 'kibana_sample*', + rollup_index: 'rollup-index', + cron: '0 0 0 ? * 7', + groups: { + date_histogram: { + interval: '24h', + field: 'timestamp', + delay: '1d', + time_zone: 'UTC' + } + }, + metrics: [], + timeout: '20s', + page_size: 1000 + }, + status: { + job_state: 'stopped', + upgraded_doc_id: true + }, + stats: { + pages_processed: 0, + documents_processed: 0, + rollups_indexed: 0, + trigger_count: 0, + index_time_in_ms: 0, + index_total: 0, + index_failures: 0, + search_time_in_ms: 0, + search_total: 0, + search_failures: 0 + } + }] +}; + +describe('', () => { + describe('detail panel', () => { + let server; + let component; + let getMetadataFromEuiTable; + let exists; + + const testBedOptions = { + memoryRouter: { + onRouter: (router) => { + // register our react memory router + registerRouter(router); + } + } + }; + + beforeEach(async () => { + server = sinon.fakeServer.create(); + server.respondImmediately = true; + + // Mock load job list + server.respondWith('GET', '/api/rollup/jobs', [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(loadJobsMock), + ]); + + // Mock all user actions tracking + server.respondWith('POST', /\/api\/user_action/, [200, { 'Content-Type': 'application/json' }, '']); + + const initTestBed = registerTestBed(JobList, {}, createRollupJobsStore()); + ({ component, exists, getMetadataFromEuiTable } = initTestBed(undefined, testBedOptions)); + + await nextTick(); // We need to wait next tick for the mock server response to comes in + component.update(); + }); + + test('should open the detail panel when clicking on a job in the table', () => { + const { rows } = getMetadataFromEuiTable('rollupJobsListTable'); + const button = rows[0].columns[1].reactWrapper.find('button'); + + expect(exists('rollupJobDetailFlyout')).toBe(false); // make sure it is not shown + + button.simulate('click'); + + expect(exists('rollupJobDetailFlyout')).toBe(true); + }); + + test('should add the Job id to the route query params when opening the detail panel', () => { + const { rows } = getMetadataFromEuiTable('rollupJobsListTable'); + const button = rows[0].columns[1].reactWrapper.find('button'); + + expect(getRouter().history.location.search).toEqual(''); + + button.simulate('click'); + + const { + jobs: [{ + config: { id: jobId }, + }], + } = loadJobsMock; + expect(getRouter().history.location.search).toEqual(`?job=${jobId}`); + }); + + test('should open the detail panel whenever a job id is added to the query params', () => { + expect(exists('rollupJobDetailFlyout')).toBe(false); // make sure it is not shown + + getRouter().history.replace({ search: `?job=bar` }); + + component.update(); + + expect(exists('rollupJobDetailFlyout')).toBe(true); + }); + }); +}); diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js index 222ee6822ed8e..192a0413355b8 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js @@ -378,7 +378,7 @@ export class JobTableUi extends Component { {jobs.length > 0 ? ( - + Date: Wed, 27 Mar 2019 09:50:50 -0400 Subject: [PATCH 50/96] Fix includeFields function to return root saved object properties (#33847) * Fix includeFields function to return root saved object properties * Fix broken tests --- .../service/lib/included_fields.js | 3 ++ .../service/lib/included_fields.test.js | 30 +++++++++++++++---- .../service/lib/repository.test.js | 10 ++++++- .../apis/saved_objects/find.js | 12 +++++++- .../common/suites/find.ts | 13 +++++++- 5 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/legacy/server/saved_objects/service/lib/included_fields.js b/src/legacy/server/saved_objects/service/lib/included_fields.js index 0a05b59fb9163..ce972d89afeae 100644 --- a/src/legacy/server/saved_objects/service/lib/included_fields.js +++ b/src/legacy/server/saved_objects/service/lib/included_fields.js @@ -35,5 +35,8 @@ export function includedFields(type, fields) { .map(f => `${sourceType}.${f}`) .concat('namespace') .concat('type') + .concat('references') + .concat('migrationVersion') + .concat('updated_at') .concat(fields); // v5 compatibility } diff --git a/src/legacy/server/saved_objects/service/lib/included_fields.test.js b/src/legacy/server/saved_objects/service/lib/included_fields.test.js index 37935ab9153db..d0b01638aff1a 100644 --- a/src/legacy/server/saved_objects/service/lib/included_fields.test.js +++ b/src/legacy/server/saved_objects/service/lib/included_fields.test.js @@ -26,33 +26,51 @@ describe('includedFields', () => { it('includes type', () => { const fields = includedFields('config', 'foo'); - expect(fields).toHaveLength(4); + expect(fields).toHaveLength(7); expect(fields).toContain('type'); }); it('includes namespace', () => { const fields = includedFields('config', 'foo'); - expect(fields).toHaveLength(4); + expect(fields).toHaveLength(7); expect(fields).toContain('namespace'); }); + it('includes references', () => { + const fields = includedFields('config', 'foo'); + expect(fields).toHaveLength(7); + expect(fields).toContain('references'); + }); + + it('includes migrationVersion', () => { + const fields = includedFields('config', 'foo'); + expect(fields).toHaveLength(7); + expect(fields).toContain('migrationVersion'); + }); + + it('includes updated_at', () => { + const fields = includedFields('config', 'foo'); + expect(fields).toHaveLength(7); + expect(fields).toContain('updated_at'); + }); + it('accepts field as string', () => { const fields = includedFields('config', 'foo'); - expect(fields).toHaveLength(4); + expect(fields).toHaveLength(7); expect(fields).toContain('config.foo'); }); it('accepts fields as an array', () => { const fields = includedFields('config', ['foo', 'bar']); - expect(fields).toHaveLength(6); + expect(fields).toHaveLength(9); expect(fields).toContain('config.foo'); expect(fields).toContain('config.bar'); }); it('uses wildcard when type is not provided', () => { const fields = includedFields(undefined, 'foo'); - expect(fields).toHaveLength(4); + expect(fields).toHaveLength(7); expect(fields).toContain('*.foo'); }); @@ -60,7 +78,7 @@ describe('includedFields', () => { it('includes legacy field path', () => { const fields = includedFields('config', ['foo', 'bar']); - expect(fields).toHaveLength(6); + expect(fields).toHaveLength(9); expect(fields).toContain('foo'); expect(fields).toContain('bar'); }); diff --git a/src/legacy/server/saved_objects/service/lib/repository.test.js b/src/legacy/server/saved_objects/service/lib/repository.test.js index 0f3ab394195db..d336e334557c4 100644 --- a/src/legacy/server/saved_objects/service/lib/repository.test.js +++ b/src/legacy/server/saved_objects/service/lib/repository.test.js @@ -1224,7 +1224,15 @@ describe('SavedObjectsRepository', () => { expect(callAdminCluster).toHaveBeenCalledWith( expect.any(String), expect.objectContaining({ - _source: ['foo.title', 'namespace', 'type', 'title'], + _source: [ + 'foo.title', + 'namespace', + 'type', + 'references', + 'migrationVersion', + 'updated_at', + 'title', + ], }) ); diff --git a/test/api_integration/apis/saved_objects/find.js b/test/api_integration/apis/saved_objects/find.js index 3ad2ca3f50571..13722183f7720 100644 --- a/test/api_integration/apis/saved_objects/find.js +++ b/test/api_integration/apis/saved_objects/find.js @@ -46,7 +46,17 @@ export default function ({ getService }) { attributes: { 'title': 'Count of requests' }, - references: [], + migrationVersion: { + visualization: '7.0.0', + }, + references: [ + { + id: '91200a00-9efd-11e7-acb3-3dab96693fab', + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + }, + ], + updated_at: '2017-09-21T18:51:23.794Z', } ] }); diff --git a/x-pack/test/saved_object_api_integration/common/suites/find.ts b/x-pack/test/saved_object_api_integration/common/suites/find.ts index f00697889a3b3..c89380de2de6d 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/find.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/find.ts @@ -68,6 +68,7 @@ export function findTestSuiteFactory(esArchiver: any, supertest: SuperTest) name: 'My favorite global object', }, references: [], + updated_at: '2017-09-21T18:59:16.270Z', }, ], }); @@ -100,7 +101,17 @@ export function findTestSuiteFactory(esArchiver: any, supertest: SuperTest) attributes: { title: 'Count of requests', }, - references: [], + migrationVersion: { + visualization: '7.0.0', + }, + references: [ + { + id: `${getIdPrefix(spaceId)}91200a00-9efd-11e7-acb3-3dab96693fab`, + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + }, + ], + updated_at: '2017-09-21T18:51:23.794Z', }, ], }); From f244583a3ef73facfb390433cefb1205b0e85112 Mon Sep 17 00:00:00 2001 From: Corey Robertson Date: Wed, 27 Mar 2019 10:02:47 -0400 Subject: [PATCH 51/96] Force consistent canvasCheckered colors (#33786) --- x-pack/plugins/canvas/public/style/main.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/canvas/public/style/main.scss b/x-pack/plugins/canvas/public/style/main.scss index 0130a2fbe77c0..ca22b3648a4da 100644 --- a/x-pack/plugins/canvas/public/style/main.scss +++ b/x-pack/plugins/canvas/public/style/main.scss @@ -14,6 +14,7 @@ } .canvasCheckered { + background-color: $euiColorGhost; background-image: linear-gradient(45deg, #ddd 25%, transparent 25%), linear-gradient(-45deg, #ddd 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ddd 75%), From d99497ab1700da471d745cec0bcedcda3a33fb2d Mon Sep 17 00:00:00 2001 From: Daniil Suleiman <31325372+sulemanof@users.noreply.github.com> Date: Wed, 27 Mar 2019 17:08:49 +0300 Subject: [PATCH 52/96] Fix TSVB auto apply changes on every click (#33710) --- .../metrics/public/components/vis_editor.js | 342 +++++++++--------- .../components/vis_editor_visualization.js | 155 ++++---- .../vis_editor_visualization.test.js | 27 +- 3 files changed, 261 insertions(+), 263 deletions(-) diff --git a/src/legacy/core_plugins/metrics/public/components/vis_editor.js b/src/legacy/core_plugins/metrics/public/components/vis_editor.js index 5c53bddf9bd27..c1701552a8936 100644 --- a/src/legacy/core_plugins/metrics/public/components/vis_editor.js +++ b/src/legacy/core_plugins/metrics/public/components/vis_editor.js @@ -1,173 +1,169 @@ -/* - * 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 PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import * as Rx from 'rxjs'; -import { share } from 'rxjs/operators'; -import VisEditorVisualization from './vis_editor_visualization'; -import Visualization from './visualization'; -import VisPicker from './vis_picker'; -import PanelConfig from './panel_config'; -import brushHandler from '../lib/create_brush_handler'; -import { fetchIndexPatternFields } from '../lib/fetch_fields'; - -class VisEditor extends Component { - constructor(props) { - super(props); - const { vis } = props; - this.appState = vis.API.getAppState(); - this.state = { - model: props.visParams, - dirty: false, - autoApply: true, - visFields: props.visFields - }; - this.onBrush = brushHandler(props.vis.API.timeFilter); - this.visDataSubject = new Rx.Subject(); - this.visData$ = this.visDataSubject.asObservable().pipe(share()); - } - - get uiState() { - return this.props.vis.getUiState(); - } - - getConfig = (...args) => { - return this.props.config.get(...args); - }; - - handleUiState = (field, value) => { - this.props.vis.uiStateVal(field, value); - }; - - handleChange = async (partialModel) => { - const nextModel = { ...this.state.model, ...partialModel }; - this.props.vis.params = nextModel; - if (this.state.autoApply) { - this.props.vis.updateState(); - } - this.setState({ - model: nextModel, - dirty: !this.state.autoApply - }); - const { params, fields } = this.props.vis; - fetchIndexPatternFields(params, fields).then(visFields => { - this.setState({ visFields }); - }); - }; - - handleCommit = () => { - this.props.vis.updateState(); - this.setState({ dirty: false }); - }; - - handleAutoApplyToggle = (event) => { - this.setState({ autoApply: event.target.checked }); - }; - - onDataChange = ({ visData }) => { - this.visDataSubject.next(visData); - }; - - render() { - if (!this.props.isEditorMode) { - if (!this.props.visParams || !this.props.visData) { - return null; - } - return ( - - ); - } - - const { model } = this.state; - - if (model) { - return ( -
    -
    - -
    - -
    - -
    -
    - ); - } - - return null; - } - - componentDidMount() { - this.props.renderComplete(); - } - - componentDidUpdate() { - this.props.renderComplete(); - } -} - -VisEditor.defaultProps = { - visData: {} -}; - -VisEditor.propTypes = { - vis: PropTypes.object, - visData: PropTypes.object, - visFields: PropTypes.object, - renderComplete: PropTypes.func, - config: PropTypes.object, - isEditorMode: PropTypes.bool, - savedObj: PropTypes.object, - timeRange: PropTypes.object, -}; - -export default VisEditor; +/* + * 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 PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import * as Rx from 'rxjs'; +import { share } from 'rxjs/operators'; +import VisEditorVisualization from './vis_editor_visualization'; +import Visualization from './visualization'; +import VisPicker from './vis_picker'; +import PanelConfig from './panel_config'; +import brushHandler from '../lib/create_brush_handler'; +import { fetchIndexPatternFields } from '../lib/fetch_fields'; + +class VisEditor extends Component { + constructor(props) { + super(props); + const { vis } = props; + this.appState = vis.API.getAppState(); + this.state = { + model: props.visParams, + dirty: false, + autoApply: true, + visFields: props.visFields + }; + this.onBrush = brushHandler(props.vis.API.timeFilter); + this.visDataSubject = new Rx.Subject(); + this.visData$ = this.visDataSubject.asObservable().pipe(share()); + } + + get uiState() { + return this.props.vis.getUiState(); + } + + getConfig = (...args) => { + return this.props.config.get(...args); + }; + + handleUiState = (field, value) => { + this.props.vis.uiStateVal(field, value); + }; + + handleChange = async (partialModel) => { + const nextModel = { ...this.state.model, ...partialModel }; + this.props.vis.params = nextModel; + if (this.state.autoApply) { + this.props.vis.updateState(); + } + this.setState({ + model: nextModel, + dirty: !this.state.autoApply + }); + const { params, fields } = this.props.vis; + fetchIndexPatternFields(params, fields).then(visFields => { + this.setState({ visFields }); + }); + }; + + handleCommit = () => { + this.props.vis.updateState(); + this.setState({ dirty: false }); + }; + + handleAutoApplyToggle = (event) => { + this.setState({ autoApply: event.target.checked }); + }; + + onDataChange = ({ visData }) => { + this.visDataSubject.next(visData); + }; + + render() { + if (!this.props.isEditorMode) { + if (!this.props.visParams || !this.props.visData) { + return null; + } + return ( + + ); + } + + const { model } = this.state; + + if (model) { + return ( +
    +
    + +
    + +
    + +
    +
    + ); + } + + return null; + } + + componentDidMount() { + this.props.renderComplete(); + } + + componentDidUpdate() { + this.props.renderComplete(); + } +} + +VisEditor.defaultProps = { + visData: {} +}; + +VisEditor.propTypes = { + vis: PropTypes.object, + visData: PropTypes.object, + visFields: PropTypes.object, + renderComplete: PropTypes.func, + config: PropTypes.object, + isEditorMode: PropTypes.bool, + savedObj: PropTypes.object, + timeRange: PropTypes.object, +}; + +export default VisEditor; diff --git a/src/legacy/core_plugins/metrics/public/components/vis_editor_visualization.js b/src/legacy/core_plugins/metrics/public/components/vis_editor_visualization.js index c6ba52f34841f..daf2b87e44e15 100644 --- a/src/legacy/core_plugins/metrics/public/components/vis_editor_visualization.js +++ b/src/legacy/core_plugins/metrics/public/components/vis_editor_visualization.js @@ -18,7 +18,7 @@ */ import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import { get } from 'lodash'; +import { get, isEqual } from 'lodash'; import { keyCodes, EuiFlexGroup, EuiFlexItem, EuiButton, EuiText, EuiSwitch } from '@elastic/eui'; import { getVisualizeLoader } from 'ui/visualize/loader/visualize_loader'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; @@ -35,74 +35,54 @@ class VisEditorVisualization extends Component { panelInterval: 0, }; - this.handleMouseUp = this.handleMouseUp.bind(this); - this.handleMouseDown = this.handleMouseDown.bind(this); - this.onSizeHandleKeyDown = this.onSizeHandleKeyDown.bind(this); - this._visEl = React.createRef(); this._subscription = null; } - handleMouseDown() { + handleMouseDown = () => { + window.addEventListener('mouseup', this.handleMouseUp); this.setState({ dragging: true }); - } + }; - handleMouseUp() { + handleMouseUp = () => { + window.removeEventListener('mouseup', this.handleMouseUp); this.setState({ dragging: false }); - } - - componentWillMount() { - this.handleMouseMove = (event) => { - if (this.state.dragging) { - this.setState((prevState) => ({ - height: Math.max(MIN_CHART_HEIGHT, prevState.height + event.movementY), - })); - } - }; - window.addEventListener('mousemove', this.handleMouseMove); - window.addEventListener('mouseup', this.handleMouseUp); - } + }; - componentWillUnmount() { - window.removeEventListener('mousemove', this.handleMouseMove); - window.removeEventListener('mouseup', this.handleMouseUp); - if (this._handler) { - this._handler.destroy(); - } - if (this._subscription) { - this._subscription.unsubscribe(); + handleMouseMove = (event) => { + if (this.state.dragging) { + this.setState((prevState) => ({ + height: Math.max(MIN_CHART_HEIGHT, prevState.height + event.movementY), + })); } - } - - onUpdate = () => { - this._handler.update({ - timeRange: this.props.timeRange, - }); }; - _loadVisualization() { - getVisualizeLoader().then(loader => { - if (!this._visEl.current) { - // In case the visualize loader isn't done before the component is unmounted. - return; - } + async _loadVisualization() { + const loader = await getVisualizeLoader(); - this._loader = loader; - this._handler = this._loader.embedVisualizationWithSavedObject(this._visEl.current, this.props.savedObj, { - uiState: this.props.uiState, - listenOnChange: false, - timeRange: this.props.timeRange, - appState: this.props.appState, - }); + if (!this._visEl.current) { + // In case the visualize loader isn't done before the component is unmounted. + return; + } - this._subscription = this._handler.data$.subscribe((data) => { - this.setPanelInterval(data.visData); - this.props.onDataChange(data); - }); + const { + uiState, + timeRange, + appState, + savedObj, + onDataChange + } = this.props; + + this._handler = loader.embedVisualizationWithSavedObject(this._visEl.current, savedObj, { + listenOnChange: false, + uiState, + timeRange, + appState, + }); - if (this._handlerUpdateHasAlreadyBeenTriggered) { - this.onUpdate(); - } + this._subscription = this._handler.data$.subscribe((data) => { + this.setPanelInterval(data.visData); + onDataChange(data); }); } @@ -114,26 +94,13 @@ class VisEditorVisualization extends Component { } } - componentDidUpdate() { - if (!this._handler) { - this._handlerUpdateHasAlreadyBeenTriggered = true; - return; - } - - this.onUpdate(); - } - - componentDidMount() { - this._loadVisualization(); - } - /** * Resize the chart height when pressing up/down while the drag handle * for resizing has the focus. * We use 15px steps to do the scaling and make sure the chart has at least its * defined minimum width (MIN_CHART_HEIGHT). */ - onSizeHandleKeyDown(ev) { + onSizeHandleKeyDown = (ev) => { const { keyCode } = ev; if (keyCode === keyCodes.UP || keyCode === keyCodes.DOWN) { ev.preventDefault(); @@ -174,9 +141,41 @@ class VisEditorVisualization extends Component { } } + componentWillUnmount() { + window.removeEventListener('mousemove', this.handleMouseMove); + window.removeEventListener('mouseup', this.handleMouseUp); + if (this._handler) { + this._handler.destroy(); + } + if (this._subscription) { + this._subscription.unsubscribe(); + } + } + + componentDidMount() { + window.addEventListener('mousemove', this.handleMouseMove); + this._loadVisualization(); + } + + componentDidUpdate(prevProps) { + if (this._handler && !isEqual(this.props.timeRange, prevProps.timeRange)) { + this._handler.update({ + timeRange: this.props.timeRange, + }); + } + } + render() { - const { dirty, autoApply } = this.props; + const { + dirty, + autoApply, + title, + description, + onToggleAutoApply, + onCommit + } = this.props; const style = { height: this.state.height }; + if (this.state.dragging) { style.userSelect = 'none'; } @@ -209,7 +208,7 @@ class VisEditorVisualization extends Component { defaultMessage="Auto apply" />)} checked={autoApply} - onChange={this.props.onToggleAutoApply} + onChange={onToggleAutoApply} /> @@ -220,9 +219,7 @@ class VisEditorVisualization extends Component {

    @@ -239,7 +236,7 @@ class VisEditorVisualization extends Component { {!autoApply && - + @@ -284,17 +281,13 @@ class VisEditorVisualization extends Component { VisEditorVisualization.propTypes = { model: PropTypes.object, - onBrush: PropTypes.func, - onChange: PropTypes.func, onCommit: PropTypes.func, - onUiState: PropTypes.func, uiState: PropTypes.object, onToggleAutoApply: PropTypes.func, savedObj: PropTypes.object, timeRange: PropTypes.object, dirty: PropTypes.bool, autoApply: PropTypes.bool, - dateFormat: PropTypes.string, appState: PropTypes.object, }; diff --git a/src/legacy/core_plugins/metrics/public/components/vis_editor_visualization.test.js b/src/legacy/core_plugins/metrics/public/components/vis_editor_visualization.test.js index 146afeb07605d..b16f9e2ea22e0 100644 --- a/src/legacy/core_plugins/metrics/public/components/vis_editor_visualization.test.js +++ b/src/legacy/core_plugins/metrics/public/components/vis_editor_visualization.test.js @@ -35,13 +35,9 @@ describe('getVisualizeLoader', () => { } }; const loaderMock = { - embedVisualizationWithSavedObject: () => { - return handlerMock; - } - }; - require('ui/visualize/loader/visualize_loader').getVisualizeLoader = async () => { - return loaderMock; + embedVisualizationWithSavedObject: () => handlerMock, }; + require('ui/visualize/loader/visualize_loader').getVisualizeLoader = async () => loaderMock; }); it('should not call _handler.update until getVisualizeLoader returns _handler', async () => { @@ -50,12 +46,25 @@ describe('getVisualizeLoader', () => { ); // Set prop to force DOM change and componentDidUpdate to be triggered - wrapper.setProps({ dirty: true }); + wrapper.setProps({ + timeRange: { + from: '2019-03-20T20:35:37.637Z', + to: '2019-03-23T18:40:16.486Z' + } + }); + + expect(updateStub).not.toHaveBeenCalled(); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); - // Ensure the state changes are reflected - wrapper.update(); + + // Set prop to force DOM change and componentDidUpdate to be triggered + wrapper.setProps({ + timeRange: { + from: 'now/d', + to: 'now/d' + } + }); expect(updateStub).toHaveBeenCalled(); }); From 411a3fbbbca6185aa3037a51e6f87f4c6b61dff9 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Wed, 27 Mar 2019 15:09:33 +0100 Subject: [PATCH 53/96] Use refresh token for any access token error with 401 status code and re-authentication user for any refresh token error with 400 status code. (#33777) * Use refresh token for any access token error with 401 status code and re-initiate SAML handshake for any refresh token error with 400 status code. * Switch from `expect.js` to `@kbn/expect`. * Review#1: repurpose redundant tests to test token failures with 500 code. --- .../authentication/__tests__/authenticator.js | 2 +- .../providers/__tests__/token.js | 85 ++++++++++--------- .../lib/authentication/providers/saml.test.ts | 72 ++++++---------- .../lib/authentication/providers/saml.ts | 41 +++------ .../lib/authentication/providers/token.js | 18 ++-- .../apis/security/saml_login.js | 55 +++++++++++- x-pack/test/saml_api_integration/config.js | 1 + .../token_api_integration/auth/session.js | 32 +++++++ 8 files changed, 185 insertions(+), 121 deletions(-) diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js index cf391b4bfdfc0..58cffca347e35 100644 --- a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js +++ b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js @@ -372,7 +372,7 @@ describe('Authenticator', () => { session.clear.resolves(); cluster.callWithRequest - .withArgs(request).rejects({ body: { error: { reason: 'token expired' } } }); + .withArgs(request).rejects({ statusCode: 401 }); cluster.callWithInternalUser.withArgs('shield.getAccessToken').rejects( Boom.badRequest('refresh token expired') diff --git a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js index b13fc1ce8934f..6c99a78847b6d 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js +++ b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js @@ -137,7 +137,7 @@ describe('TokenAuthenticationProvider', () => { callWithRequest .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate') - .returns(Promise.reject({ body: { error: { reason: 'token expired' } } })); + .rejects({ statusCode: 401 }); callWithInternalUser .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } }) @@ -176,26 +176,6 @@ describe('TokenAuthenticationProvider', () => { expect(authenticationResult.notHandled()).to.be(true); }); - it('fails if state contains invalid credentials.', async () => { - const request = requestFixture(); - const accessToken = 'foo'; - const authorization = `Bearer ${accessToken}`; - - const authenticationError = new Error('Forbidden'); - callWithRequest - .withArgs(sinon.match({ headers: { authorization } }), 'shield.authenticate') - .returns(Promise.reject(authenticationError)); - - const authenticationResult = await provider.authenticate(request, { accessToken }); - - expect(request.headers).to.not.have.property('authorization'); - expect(authenticationResult.failed()).to.be(true); - expect(authenticationResult.user).to.be.eql(undefined); - expect(authenticationResult.state).to.be.eql(undefined); - expect(authenticationResult.error).to.be.eql(authenticationError); - sinon.assert.calledOnce(callWithRequest); - }); - it('authenticates only via `authorization` header even if state is available.', async () => { const accessToken = 'foo'; const authorization = `Bearer ${accessToken}`; @@ -263,14 +243,14 @@ describe('TokenAuthenticationProvider', () => { expect(authenticationResult.error).to.be.eql(authenticationError); }); - it('fails when header contains a rejected token', async () => { + it('fails if authentication with token from header fails with unknown error', async () => { const authorization = `Bearer foo`; const request = requestFixture({ headers: { authorization } }); - const authenticationError = new Error('Forbidden'); + const authenticationError = new errors.InternalServerError('something went wrong'); callWithRequest .withArgs(request, 'shield.authenticate') - .returns(Promise.reject(authenticationError)); + .rejects(authenticationError); const authenticationResult = await provider.authenticate(request); @@ -282,14 +262,14 @@ describe('TokenAuthenticationProvider', () => { expect(authenticationResult.error).to.be.eql(authenticationError); }); - it('fails when session contains a rejected token', async () => { + it('fails if authentication with token from state fails with unknown error.', async () => { const accessToken = 'foo'; const request = requestFixture(); - const authenticationError = new Error('Forbidden'); + const authenticationError = new errors.InternalServerError('something went wrong'); callWithRequest - .withArgs(request, 'shield.authenticate') - .returns(Promise.reject(authenticationError)); + .withArgs(sinon.match({ headers: { authorization: `Bearer ${accessToken}` } }), 'shield.authenticate') + .rejects(authenticationError); const authenticationResult = await provider.authenticate(request, { accessToken }); @@ -302,17 +282,17 @@ describe('TokenAuthenticationProvider', () => { expect(authenticationResult.error).to.be.eql(authenticationError); }); - it('fails if token refresh is rejected', async () => { + it('fails if token refresh is rejected with unknown error', async () => { const request = requestFixture(); callWithRequest .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate') - .returns(Promise.reject({ body: { error: { reason: 'token expired' } } })); + .rejects({ statusCode: 401 }); - const authenticationError = new Error('failed to refresh token'); + const refreshError = new errors.InternalServerError('failed to refresh token'); callWithInternalUser .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } }) - .returns(Promise.reject(authenticationError)); + .rejects(refreshError); const accessToken = 'foo'; const refreshToken = 'bar'; @@ -325,7 +305,36 @@ describe('TokenAuthenticationProvider', () => { expect(authenticationResult.failed()).to.be(true); expect(authenticationResult.user).to.be.eql(undefined); expect(authenticationResult.state).to.be.eql(undefined); - expect(authenticationResult.error).to.be.eql(authenticationError); + expect(authenticationResult.error).to.be.eql(refreshError); + }); + + it('redirects non-AJAX requests to /login and clears session if token document is missing', async () => { + const request = requestFixture({ path: '/some-path' }); + + callWithRequest + .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate') + .rejects({ + statusCode: 500, + body: { error: { reason: 'token document is missing and must be present' } }, + }); + + callWithInternalUser + .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } }) + .rejects(new errors.BadRequest('failed to refresh token')); + + const accessToken = 'foo'; + const refreshToken = 'bar'; + const authenticationResult = await provider.authenticate(request, { accessToken, refreshToken }); + + sinon.assert.calledOnce(callWithRequest); + sinon.assert.calledOnce(callWithInternalUser); + + expect(request.headers).to.not.have.property('authorization'); + expect(authenticationResult.redirected()).to.be(true); + expect(authenticationResult.redirectURL).to.be('/base-path/login?next=%2Fsome-path'); + expect(authenticationResult.user).to.be.eql(undefined); + expect(authenticationResult.state).to.be.eql(null); + expect(authenticationResult.error).to.be.eql(undefined); }); it('redirects non-AJAX requests to /login and clears session if token refresh fails with 400 error', async () => { @@ -333,7 +342,7 @@ describe('TokenAuthenticationProvider', () => { callWithRequest .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate') - .rejects({ body: { error: { reason: 'token expired' } } }); + .rejects({ statusCode: 401 }); callWithInternalUser .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } }) @@ -359,7 +368,7 @@ describe('TokenAuthenticationProvider', () => { callWithRequest .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate') - .rejects({ body: { error: { reason: 'token expired' } } }); + .rejects({ statusCode: 401 }); const authenticationError = new errors.BadRequest('failed to refresh token'); callWithInternalUser @@ -385,16 +394,16 @@ describe('TokenAuthenticationProvider', () => { callWithRequest .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate') - .returns(Promise.reject({ body: { error: { reason: 'token expired' } } })); + .rejects({ statusCode: 401 }); callWithInternalUser .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } }) .returns(Promise.resolve({ access_token: 'newfoo', refresh_token: 'newbar' })); - const authenticationError = new Error('Some error'); + const authenticationError = new errors.AuthenticationException('Some error'); callWithRequest .withArgs(sinon.match({ headers: { authorization: 'Bearer newfoo' } }), 'shield.authenticate') - .returns(Promise.reject(authenticationError)); + .rejects(authenticationError); const accessToken = 'foo'; const refreshToken = 'bar'; diff --git a/x-pack/plugins/security/server/lib/authentication/providers/saml.test.ts b/x-pack/plugins/security/server/lib/authentication/providers/saml.test.ts index 5498ab0854477..e5df0d09a7080 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/saml.test.ts +++ b/x-pack/plugins/security/server/lib/authentication/providers/saml.test.ts @@ -212,7 +212,7 @@ describe('SAMLAuthenticationProvider', () => { it('fails if token from the state is rejected because of unknown reason.', async () => { const request = requestFixture(); - const failureReason = new Error('Token is not valid!'); + const failureReason = { statusCode: 500, message: 'Token is not valid!' }; callWithRequest.withArgs(request, 'shield.authenticate').rejects(failureReason); const authenticationResult = await provider.authenticate(request, { @@ -235,7 +235,7 @@ describe('SAMLAuthenticationProvider', () => { sinon.match({ headers: { authorization: 'Bearer expired-token' } }), 'shield.authenticate' ) - .rejects({ body: { error: { reason: 'token expired' } } }); + .rejects({ statusCode: 401 }); callWithRequest .withArgs( @@ -264,7 +264,7 @@ describe('SAMLAuthenticationProvider', () => { }); }); - it('fails if token from the state is expired and refresh attempt failed too.', async () => { + it('fails if token from the state is expired and refresh attempt failed with unknown reason too.', async () => { const request = requestFixture(); callWithRequest @@ -272,9 +272,12 @@ describe('SAMLAuthenticationProvider', () => { sinon.match({ headers: { authorization: 'Bearer expired-token' } }), 'shield.authenticate' ) - .rejects({ body: { error: { reason: 'token expired' } } }); + .rejects({ statusCode: 401 }); - const refreshFailureReason = new Error('Something is wrong with refresh token.'); + const refreshFailureReason = { + statusCode: 500, + message: 'Something is wrong with refresh token.', + }; callWithInternalUser .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'invalid-refresh-token' }, @@ -291,7 +294,7 @@ describe('SAMLAuthenticationProvider', () => { expect(authenticationResult.error).toBe(refreshFailureReason); }); - it('fails for AJAX requests with user friendly message if refresh token is used more than once.', async () => { + it('fails for AJAX requests with user friendly message if refresh token is expired.', async () => { const request = requestFixture({ headers: { 'kbn-xsrf': 'xsrf' } }); callWithRequest @@ -299,17 +302,17 @@ describe('SAMLAuthenticationProvider', () => { sinon.match({ headers: { authorization: 'Bearer expired-token' } }), 'shield.authenticate' ) - .rejects({ body: { error: { reason: 'token expired' } } }); + .rejects({ statusCode: 401 }); callWithInternalUser .withArgs('shield.getAccessToken', { - body: { grant_type: 'refresh_token', refresh_token: 'invalid-refresh-token' }, + body: { grant_type: 'refresh_token', refresh_token: 'expired-refresh-token' }, }) - .rejects({ body: { error_description: 'token has already been refreshed' } }); + .rejects({ statusCode: 400 }); const authenticationResult = await provider.authenticate(request, { accessToken: 'expired-token', - refreshToken: 'invalid-refresh-token', + refreshToken: 'expired-refresh-token', }); expect(request.headers).not.toHaveProperty('authorization'); @@ -319,7 +322,7 @@ describe('SAMLAuthenticationProvider', () => { ); }); - it('initiates SAML handshake for non-AJAX requests if refresh token is used more than once.', async () => { + it('initiates SAML handshake for non-AJAX requests if access token document is missing.', async () => { const request = requestFixture({ path: '/some-path', basePath: '/s/foo' }); callWithInternalUser.withArgs('shield.samlPrepare').resolves({ @@ -332,17 +335,20 @@ describe('SAMLAuthenticationProvider', () => { sinon.match({ headers: { authorization: 'Bearer expired-token' } }), 'shield.authenticate' ) - .rejects({ body: { error: { reason: 'token expired' } } }); + .rejects({ + statusCode: 500, + body: { error: { reason: 'token document is missing and must be present' } }, + }); callWithInternalUser .withArgs('shield.getAccessToken', { - body: { grant_type: 'refresh_token', refresh_token: 'invalid-refresh-token' }, + body: { grant_type: 'refresh_token', refresh_token: 'expired-refresh-token' }, }) - .rejects({ body: { error_description: 'token has already been refreshed' } }); + .rejects({ statusCode: 400 }); const authenticationResult = await provider.authenticate(request, { accessToken: 'expired-token', - refreshToken: 'invalid-refresh-token', + refreshToken: 'expired-refresh-token', }); sinon.assert.calledWithExactly(callWithInternalUser, 'shield.samlPrepare', { @@ -359,34 +365,6 @@ describe('SAMLAuthenticationProvider', () => { }); }); - it('fails for AJAX requests with user friendly message if refresh token is expired.', async () => { - const request = requestFixture({ headers: { 'kbn-xsrf': 'xsrf' } }); - - callWithRequest - .withArgs( - sinon.match({ headers: { authorization: 'Bearer expired-token' } }), - 'shield.authenticate' - ) - .rejects({ body: { error: { reason: 'token expired' } } }); - - callWithInternalUser - .withArgs('shield.getAccessToken', { - body: { grant_type: 'refresh_token', refresh_token: 'expired-refresh-token' }, - }) - .rejects({ body: { error_description: 'refresh token is expired' } }); - - const authenticationResult = await provider.authenticate(request, { - accessToken: 'expired-token', - refreshToken: 'expired-refresh-token', - }); - - expect(request.headers).not.toHaveProperty('authorization'); - expect(authenticationResult.failed()).toBe(true); - expect(authenticationResult.error).toEqual( - Boom.badRequest('Both access and refresh tokens are expired.') - ); - }); - it('initiates SAML handshake for non-AJAX requests if refresh token is expired.', async () => { const request = requestFixture({ path: '/some-path', basePath: '/s/foo' }); @@ -400,13 +378,13 @@ describe('SAMLAuthenticationProvider', () => { sinon.match({ headers: { authorization: 'Bearer expired-token' } }), 'shield.authenticate' ) - .rejects({ body: { error: { reason: 'token expired' } } }); + .rejects({ statusCode: 401 }); callWithInternalUser .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'expired-refresh-token' }, }) - .rejects({ body: { error_description: 'refresh token is expired' } }); + .rejects({ statusCode: 400 }); const authenticationResult = await provider.authenticate(request, { accessToken: 'expired-token', @@ -444,7 +422,7 @@ describe('SAMLAuthenticationProvider', () => { it('fails if token from `authorization` header is rejected.', async () => { const request = requestFixture({ headers: { authorization: 'Bearer some-invalid-token' } }); - const failureReason = new Error('Token is not valid!'); + const failureReason = { statusCode: 401 }; callWithRequest.withArgs(request, 'shield.authenticate').rejects(failureReason); const authenticationResult = await provider.authenticate(request); @@ -457,7 +435,7 @@ describe('SAMLAuthenticationProvider', () => { const user = { username: 'user' }; const request = requestFixture({ headers: { authorization: 'Bearer some-invalid-token' } }); - const failureReason = new Error('Token is not valid!'); + const failureReason = { statusCode: 401 }; callWithRequest.withArgs(request, 'shield.authenticate').rejects(failureReason); callWithRequest diff --git a/x-pack/plugins/security/server/lib/authentication/providers/saml.ts b/x-pack/plugins/security/server/lib/authentication/providers/saml.ts index 8f7773e70193d..55a7fe747069f 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/saml.ts +++ b/x-pack/plugins/security/server/lib/authentication/providers/saml.ts @@ -8,6 +8,7 @@ import Boom from 'boom'; import { Request } from 'hapi'; import { Cluster } from 'src/legacy/core_plugins/elasticsearch'; import { canRedirectRequest } from '../../can_redirect_request'; +import { getErrorStatusCode } from '../../errors'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; @@ -50,16 +51,6 @@ interface ProviderState { refreshToken?: string; } -/** - * Represents error returned from Elasticsearch API. - */ -interface APIError extends Error { - body?: { - error?: { reason?: string }; - error_description?: string; - }; -} - /** * Defines the shape of the request body containing SAML response. */ @@ -76,25 +67,21 @@ interface SAMLRequestQuery { } /** - * Checks the error returned by Elasticsearch as the result of `authenticate` call and returns `true` if request - * has been rejected because of expired token, otherwise returns `false`. - * @param err Error returned from Elasticsearch. - */ -function isAccessTokenExpiredError(err?: APIError) { - return err && err.body && err.body.error && err.body.error.reason === 'token expired'; -} - -/** - * Checks the error returned by Elasticsearch as the result of `getAccessToken` call and returns `true` if - * request has been rejected because of invalid refresh token (expired after 24 hours or have been used already), - * otherwise returns `false`. + * If request with access token fails with `401 Unauthorized` then this token is no + * longer valid and we should try to refresh it. Another use case that we should + * temporarily support (until elastic/elasticsearch#38866 is fixed) is when token + * document has been removed and ES responds with `500 Internal Server Error`. * @param err Error returned from Elasticsearch. */ -function isInvalidRefreshTokenError(err: APIError) { +function isAccessTokenExpiredError(err?: any) { + const errorStatusCode = getErrorStatusCode(err); return ( - err.body && - (err.body.error_description === 'token has already been refreshed' || - err.body.error_description === 'refresh token is expired') + errorStatusCode === 401 || + (errorStatusCode === 500 && + err && + err.body && + err.body.error && + err.body.error.reason === 'token document is missing and must be present') ); } @@ -476,7 +463,7 @@ export class SAMLAuthenticationProvider { // handshake. Obviously we can't do that for AJAX requests, so we just reply with `400` and clear error message. // There are two reasons for `400` and not `401`: Elasticsearch search responds with `400` so it seems logical // to do the same on Kibana side and `401` would force user to logout and do full SLO if it's supported. - if (isInvalidRefreshTokenError(err)) { + if (getErrorStatusCode(err) === 400) { if (canRedirectRequest(request)) { this.options.log( ['debug', 'security', 'saml'], diff --git a/x-pack/plugins/security/server/lib/authentication/providers/token.js b/x-pack/plugins/security/server/lib/authentication/providers/token.js index 96d3c304c3445..74b3778a816ad 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/token.js +++ b/x-pack/plugins/security/server/lib/authentication/providers/token.js @@ -27,15 +27,23 @@ import { DeauthenticationResult } from '../deauthentication_result'; */ /** - * Checks the error returned by Elasticsearch as the result of `authenticate` call and returns `true` if request - * has been rejected because of expired token, otherwise returns `false`. + * If request with access token fails with `401 Unauthorized` then this token is no + * longer valid and we should try to refresh it. Another use case that we should + * temporarily support (until elastic/elasticsearch#38866 is fixed) is when token + * document has been removed and ES responds with `500 Internal Server Error`. * @param {Object} err Error returned from Elasticsearch. * @returns {boolean} */ function isAccessTokenExpiredError(err) { - return err.body - && err.body.error - && err.body.error.reason === 'token expired'; + const errorStatusCode = getErrorStatusCode(err); + return ( + errorStatusCode === 401 || + (errorStatusCode === 500 && + err && + err.body && + err.body.error && + err.body.error.reason === 'token document is missing and must be present') + ); } /** diff --git a/x-pack/test/saml_api_integration/apis/security/saml_login.js b/x-pack/test/saml_api_integration/apis/security/saml_login.js index a664d68d1b2d1..ca89b36c0c34d 100644 --- a/x-pack/test/saml_api_integration/apis/security/saml_login.js +++ b/x-pack/test/saml_api_integration/apis/security/saml_login.js @@ -333,7 +333,7 @@ export default function ({ getService }) { expect(apiResponse.body).to.eql({ error: 'Bad Request', - message: 'invalid_grant', + message: 'Both access and refresh tokens are expired.', statusCode: 400 }); }); @@ -390,7 +390,7 @@ export default function ({ getService }) { expect(apiResponse.body).to.eql({ error: 'Bad Request', - message: 'invalid_grant', + message: 'Both access and refresh tokens are expired.', statusCode: 400 }); }); @@ -417,7 +417,7 @@ export default function ({ getService }) { expect(apiResponse.body).to.eql({ error: 'Bad Request', - message: 'invalid_grant', + message: 'Both access and refresh tokens are expired.', statusCode: 400 }); }); @@ -502,5 +502,54 @@ export default function ({ getService }) { .expect(200); }); }); + + describe('API access with missing access token document.', () => { + let sessionCookie; + + beforeEach(async () => { + const handshakeResponse = await supertest.get('/abc/xyz') + .expect(302); + + const handshakeCookie = request.cookie(handshakeResponse.headers['set-cookie'][0]); + const samlRequestId = await getSAMLRequestId(handshakeResponse.headers.location); + + const samlAuthenticationResponse = await supertest.post('/api/security/v1/saml') + .set('kbn-xsrf', 'xxx') + .set('Cookie', handshakeCookie.cookieString()) + .send({ SAMLResponse: await createSAMLResponse({ inResponseTo: samlRequestId }) }, {}) + .expect(302); + + sessionCookie = request.cookie(samlAuthenticationResponse.headers['set-cookie'][0]); + }); + + it('should properly set cookie and start new SAML handshake', async function () { + // Let's delete tokens from `.security` index directly to simulate the case when + // Elasticsearch automatically removes access/refresh token document from the index + // after some period of time. + const esResponse = await getService('es').deleteByQuery({ + index: '.security', + q: 'doc_type:token', + refresh: true, + }); + expect(esResponse).to.have.property('deleted').greaterThan(0); + + const handshakeResponse = await supertest.get('/abc/xyz/handshake?one=two three') + .set('Cookie', sessionCookie.cookieString()) + .expect(302); + + const cookies = handshakeResponse.headers['set-cookie']; + expect(cookies).to.have.length(1); + + const handshakeCookie = request.cookie(cookies[0]); + expect(handshakeCookie.key).to.be('sid'); + expect(handshakeCookie.value).to.not.be.empty(); + expect(handshakeCookie.path).to.be('/'); + expect(handshakeCookie.httpOnly).to.be(true); + + const redirectURL = url.parse(handshakeResponse.headers.location, true /* parseQueryString */); + expect(redirectURL.href.startsWith(`https://elastic.co/sso/saml`)).to.be(true); + expect(redirectURL.query.SAMLRequest).to.not.be.empty(); + }); + }); }); } diff --git a/x-pack/test/saml_api_integration/config.js b/x-pack/test/saml_api_integration/config.js index 2a9e0fe314a00..4ac092d7f09d1 100644 --- a/x-pack/test/saml_api_integration/config.js +++ b/x-pack/test/saml_api_integration/config.js @@ -18,6 +18,7 @@ export default async function ({ readConfigFile }) { servers: xPackAPITestsConfig.get('servers'), services: { chance: kibanaAPITestsConfig.get('services.chance'), + es: kibanaAPITestsConfig.get('services.es'), supertestWithoutAuth: xPackAPITestsConfig.get('services.supertestWithoutAuth'), }, junit: { diff --git a/x-pack/test/token_api_integration/auth/session.js b/x-pack/test/token_api_integration/auth/session.js index 953873a615f53..ad7750f46ec29 100644 --- a/x-pack/test/token_api_integration/auth/session.js +++ b/x-pack/test/token_api_integration/auth/session.js @@ -5,6 +5,7 @@ */ import request from 'request'; +import expect from '@kbn/expect'; const delay = ms => new Promise(resolve => setTimeout(() => resolve(), ms)); @@ -122,5 +123,36 @@ export default function ({ getService }) { .expect(200); }); }); + + describe('API access with missing access token document.', () => { + let sessionCookie; + beforeEach(async () => sessionCookie = await createSessionCookie()); + + it('should clear cookie and redirect to login', async function () { + // Let's delete tokens from `.security` index directly to simulate the case when + // Elasticsearch automatically removes access/refresh token document from the index + // after some period of time. + const esResponse = await getService('es').deleteByQuery({ + index: '.security', + q: 'doc_type:token', + refresh: true, + }); + expect(esResponse).to.have.property('deleted').greaterThan(0); + + const response = await supertest.get('/abc/xyz/') + .set('Cookie', sessionCookie.cookieString()) + .expect('location', '/login?next=%2Fabc%2Fxyz%2F') + .expect(302); + + const cookies = response.headers['set-cookie']; + expect(cookies).to.have.length(1); + + const cookie = request.cookie(cookies[0]); + expect(cookie.key).to.be('sid'); + expect(cookie.value).to.be.empty(); + expect(cookie.path).to.be('/'); + expect(cookie.httpOnly).to.be(true); + }); + }); }); } From b20c3a1eba5ca7339c554281cbf60f91fac6b487 Mon Sep 17 00:00:00 2001 From: Chris Mark Date: Wed, 27 Mar 2019 16:19:37 +0200 Subject: [PATCH 54/96] Add Data UI for CoreDNS Metricbeat Module (#33845) Signed-off-by: Chris Mark --- .../server/tutorials/coredns_metrics/index.js | 61 +++++++++++++++++++ .../kibana/server/tutorials/register.js | 2 + 2 files changed, 63 insertions(+) create mode 100644 src/legacy/core_plugins/kibana/server/tutorials/coredns_metrics/index.js diff --git a/src/legacy/core_plugins/kibana/server/tutorials/coredns_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/coredns_metrics/index.js new file mode 100644 index 0000000000000..2d0f450688e02 --- /dev/null +++ b/src/legacy/core_plugins/kibana/server/tutorials/coredns_metrics/index.js @@ -0,0 +1,61 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; +import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions'; + +export function corednsMetricsSpecProvider(server, context) { + const moduleName = 'coredns'; + return { + id: 'corednsMetrics', + name: i18n.translate('kbn.server.tutorials.corednsMetrics.nameTitle', { + defaultMessage: 'CoreDNS metrics', + }), + category: TUTORIAL_CATEGORY.METRICS, + shortDescription: i18n.translate('kbn.server.tutorials.corednsMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from the CoreDNS server.', + }), + longDescription: i18n.translate('kbn.server.tutorials.corednsMetrics.longDescription', { + defaultMessage: 'The `coredns` Metricbeat module fetches monitoring metrics from CoreDNS. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-coredns.html', + }, + }), + // euiIconType: 'logoCoreDNS', + artifacts: { + application: { + label: i18n.translate('kbn.server.tutorials.corednsMetrics.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/kibana#/discover' + }, + dashboards: [], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-coredns.html' + } + }, + completionTimeMinutes: 10, + // previewImagePath: '/plugins/kibana/home/tutorial_resources/coredns_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, null, null, null, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName) + }; +} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/register.js b/src/legacy/core_plugins/kibana/server/tutorials/register.js index 1f0b39fef0e59..a0db02e34498b 100644 --- a/src/legacy/core_plugins/kibana/server/tutorials/register.js +++ b/src/legacy/core_plugins/kibana/server/tutorials/register.js @@ -68,6 +68,7 @@ import { mssqlMetricsSpecProvider } from './mssql_metrics'; import { natsMetricsSpecProvider } from './nats_metrics'; import { natsLogsSpecProvider } from './nats_logs'; import { zeekLogsSpecProvider } from './zeek_logs'; +import { corednsMetricsSpecProvider } from './coredns_metrics'; export function registerTutorials(server) { server.registerTutorial(systemLogsSpecProvider); @@ -121,4 +122,5 @@ export function registerTutorials(server) { server.registerTutorial(natsMetricsSpecProvider); server.registerTutorial(natsLogsSpecProvider); server.registerTutorial(zeekLogsSpecProvider); + server.registerTutorial(corednsMetricsSpecProvider); } From 465d37bbac29a886530e79cad39250e13be2c6fe Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 27 Mar 2019 08:33:34 -0600 Subject: [PATCH 55/96] [Maps] layer specific filtering (#33209) * render filters section in layer details * add popover with QueryBar * show index pattern type ahead * scss * add custom button to QueryBar * add setQuery action creator * wire together layer query to search source * remove old comment * update heatmap layer to consider layerQuery during resync logic * update getBounds to apply layer query * fix QueryBar typescript problems * add functional test for layer query * more typescript nonsense * fix jest test * use EuiPopover instead of EuiModal * close popover on button click * fix functional test with popover change * add empty state help text and use small padding on EuiCodeBlock * query_bar renderUpdateButton return early if not this.props.showDatePicker --- .../public/query_bar/components/query_bar.tsx | 22 ++- .../maps/public/actions/store_actions.js | 13 ++ .../__snapshots__/view.test.js.snap | 1 + .../public/components/layer_panel/_index.scss | 1 + .../filter_editor/_filter_editor.scss | 4 + .../filter_editor/filter_editor.js | 184 ++++++++++++++++++ .../layer_panel/filter_editor/index.js | 27 +++ .../public/components/layer_panel/view.js | 18 ++ .../components/layer_panel/view.test.js | 7 + .../public/shared/layers/heatmap_layer.js | 44 +++-- .../maps/public/shared/layers/layer.js | 8 + .../es_geo_grid_source/es_geo_grid_source.js | 1 - .../public/shared/layers/sources/es_source.js | 28 ++- .../public/shared/layers/sources/source.js | 4 + .../maps/public/shared/layers/vector_layer.js | 9 +- .../functional/apps/maps/es_search_source.js | 25 +++ .../test/functional/page_objects/gis_page.js | 13 ++ 17 files changed, 371 insertions(+), 38 deletions(-) create mode 100644 x-pack/plugins/maps/public/components/layer_panel/filter_editor/_filter_editor.scss create mode 100644 x-pack/plugins/maps/public/components/layer_panel/filter_editor/filter_editor.js create mode 100644 x-pack/plugins/maps/public/components/layer_panel/filter_editor/index.js diff --git a/src/legacy/ui/public/query_bar/components/query_bar.tsx b/src/legacy/ui/public/query_bar/components/query_bar.tsx index 1f8a66cba723d..d7d52881567ed 100644 --- a/src/legacy/ui/public/query_bar/components/query_bar.tsx +++ b/src/legacy/ui/public/query_bar/components/query_bar.tsx @@ -97,6 +97,7 @@ interface Props { refreshInterval?: number; showAutoRefreshOnly?: boolean; onRefreshChange?: (options: { isPaused: boolean; refreshInterval: number }) => void; + customSubmitButton?: any; } interface State { @@ -634,7 +635,9 @@ export class QueryBarUI extends Component { } private renderUpdateButton() { - const button = ( + const button = this.props.customSubmitButton ? ( + React.cloneElement(this.props.customSubmitButton, { onClick: this.onClickSubmitButton }) + ) : ( { data-test-subj="querySubmitButton" /> ); - if (this.props.showDatePicker) { - return ( - - {this.renderDatePicker()} - {button} - - ); - } else { + + if (!this.props.showDatePicker) { return button; } + + return ( + + {this.renderDatePicker()} + {button} + + ); } private renderDatePicker() { diff --git a/x-pack/plugins/maps/public/actions/store_actions.js b/x-pack/plugins/maps/public/actions/store_actions.js index 7f042d409ee27..0c1c81f471a3f 100644 --- a/x-pack/plugins/maps/public/actions/store_actions.js +++ b/x-pack/plugins/maps/public/actions/store_actions.js @@ -481,6 +481,19 @@ export function updateLayerAlpha(id, alpha) { }; } +export function setLayerQuery(id, query) { + return (dispatch) => { + dispatch({ + type: UPDATE_LAYER_PROP, + id, + propName: 'query', + newValue: query, + }); + + dispatch(syncDataForLayer(id)); + }; +} + export function removeSelectedLayer() { return (dispatch, getState) => { const state = getState(); diff --git a/x-pack/plugins/maps/public/components/layer_panel/__snapshots__/view.test.js.snap b/x-pack/plugins/maps/public/components/layer_panel/__snapshots__/view.test.js.snap index d260aebd67d5f..4aeb2969a4829 100644 --- a/x-pack/plugins/maps/public/components/layer_panel/__snapshots__/view.test.js.snap +++ b/x-pack/plugins/maps/public/components/layer_panel/__snapshots__/view.test.js.snap @@ -103,6 +103,7 @@ exports[`LayerPanel is rendered 1`] = ` "getImmutableSourceProperties": [Function], "getLayerTypeIconName": [Function], "isJoinable": [Function], + "supportsElasticsearchFilters": [Function], } } /> diff --git a/x-pack/plugins/maps/public/components/layer_panel/_index.scss b/x-pack/plugins/maps/public/components/layer_panel/_index.scss index 676db6f5a0415..2008a10d95bd4 100644 --- a/x-pack/plugins/maps/public/components/layer_panel/_index.scss +++ b/x-pack/plugins/maps/public/components/layer_panel/_index.scss @@ -1,3 +1,4 @@ @import './layer_panel'; +@import './filter_editor/filter_editor'; @import './join_editor/resources/join'; @import './layer_settings/layer_settings'; diff --git a/x-pack/plugins/maps/public/components/layer_panel/filter_editor/_filter_editor.scss b/x-pack/plugins/maps/public/components/layer_panel/filter_editor/_filter_editor.scss new file mode 100644 index 0000000000000..089f9ab08a1f7 --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/filter_editor/_filter_editor.scss @@ -0,0 +1,4 @@ +.mapFilterEditor { + width: calc(95vw - #{$euiSizeXXL * 11}); + overflow-y: visible; +} diff --git a/x-pack/plugins/maps/public/components/layer_panel/filter_editor/filter_editor.js b/x-pack/plugins/maps/public/components/layer_panel/filter_editor/filter_editor.js new file mode 100644 index 0000000000000..c260b67d7de71 --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/filter_editor/filter_editor.js @@ -0,0 +1,184 @@ +/* + * 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 chrome from 'ui/chrome'; +import React, { Component, Fragment } from 'react'; + +import { + EuiButton, + EuiCodeBlock, + EuiTitle, + EuiPopover, + EuiSpacer, + EuiText, + EuiTextColor, +} from '@elastic/eui'; + +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { QueryBar } from 'ui/query_bar'; +import { indexPatternService } from '../../../kibana_services'; +import { Storage } from 'ui/storage'; + +const settings = chrome.getUiSettingsClient(); +const localStorage = new Storage(window.localStorage); + +export class FilterEditor extends Component { + + state = { + isPopoverOpen: false, + indexPatterns: [], + } + + componentDidMount() { + this._isMounted = true; + this._loadIndexPatterns(); + } + + componentWillUnmount() { + this._isMounted = false; + } + + _loadIndexPatterns = async () => { + const indexPatternIds = this.props.layer.getIndexPatternIds(); + const indexPatterns = []; + const getIndexPatternPromises = indexPatternIds.map(async (indexPatternId) => { + try { + const indexPattern = await indexPatternService.get(indexPatternId); + indexPatterns.push(indexPattern); + } catch(err) { + // unable to fetch index pattern + } + }); + + await Promise.all(getIndexPatternPromises); + + if (!this._isMounted) { + return; + } + + this.setState({ indexPatterns }); + } + + _toggle = () => { + this.setState(prevState => ({ + isPopoverOpen: !prevState.isPopoverOpen, + })); + } + + _close = () => { + this.setState({ isPopoverOpen: false }); + } + + _onQueryChange = ({ query }) => { + this.props.setLayerQuery(this.props.layer.getId(), query); + this._close(); + } + + _renderQueryPopover() { + const layerQuery = this.props.layer.getQuery(); + + return ( + +
    + + + + } + /> +
    +
    + ); + } + + _renderQuery() { + const query = this.props.layer.getQuery(); + if (!query || !query.query) { + return ( + +

    + + + +

    +
    + ); + } + + return ( + + + {query.query} + + + + ); + } + + _renderOpenButton() { + const query = this.props.layer.getQuery(); + const openButtonLabel = query && query.query + ? i18n.translate('xpack.maps.layerPanel.filterEditor.editFilterButtonLabel', { + defaultMessage: 'Edit filter' + }) + : i18n.translate('xpack.maps.layerPanel.filterEditor.addFilterButtonLabel', { + defaultMessage: 'Add filter' + }); + + return ( + + {openButtonLabel} + + ); + } + + render() { + return ( + + +
    + +
    +
    + + {this._renderQuery()} + + {this._renderQueryPopover()} +
    + ); + } +} diff --git a/x-pack/plugins/maps/public/components/layer_panel/filter_editor/index.js b/x-pack/plugins/maps/public/components/layer_panel/filter_editor/index.js new file mode 100644 index 0000000000000..ceedf7661f69a --- /dev/null +++ b/x-pack/plugins/maps/public/components/layer_panel/filter_editor/index.js @@ -0,0 +1,27 @@ +/* + * 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 { connect } from 'react-redux'; +import { FilterEditor } from './filter_editor'; +import { getSelectedLayer } from '../../../selectors/map_selectors'; +import { setLayerQuery } from '../../../actions/store_actions'; + +function mapStateToProps(state = {}) { + return { + layer: getSelectedLayer(state), + }; +} + +function mapDispatchToProps(dispatch) { + return { + setLayerQuery: (layerId, query) => { + dispatch(setLayerQuery(layerId, query)); + } + }; +} + +const connectedFilterEditor = connect(mapStateToProps, mapDispatchToProps)(FilterEditor); +export { connectedFilterEditor as FilterEditor }; diff --git a/x-pack/plugins/maps/public/components/layer_panel/view.js b/x-pack/plugins/maps/public/components/layer_panel/view.js index 20a5a2669484b..2fff3bf419873 100644 --- a/x-pack/plugins/maps/public/components/layer_panel/view.js +++ b/x-pack/plugins/maps/public/components/layer_panel/view.js @@ -7,6 +7,7 @@ import React, { Fragment } from 'react'; import { StyleTabs } from './style_tabs'; +import { FilterEditor } from './filter_editor'; import { JoinEditor } from './join_editor'; import { FlyoutFooter } from './flyout_footer'; import { LayerErrors } from './layer_errors'; @@ -89,6 +90,21 @@ export class LayerPanel extends React.Component { } } + _renderFilterSection() { + if (!this.props.selectedLayer.supportsElasticsearchFilters()) { + return null; + } + + return ( + + + + + + + ); + } + _renderJoinSection() { if (!this.props.selectedLayer.isJoinable()) { return null; @@ -184,6 +200,8 @@ export class LayerPanel extends React.Component { + {this._renderFilterSection()} + {this._renderJoinSection()} diff --git a/x-pack/plugins/maps/public/components/layer_panel/view.test.js b/x-pack/plugins/maps/public/components/layer_panel/view.test.js index 6a5208ce13c0b..b81f870d4c298 100644 --- a/x-pack/plugins/maps/public/components/layer_panel/view.test.js +++ b/x-pack/plugins/maps/public/components/layer_panel/view.test.js @@ -16,6 +16,12 @@ jest.mock('./join_editor', () => ({ } })); +jest.mock('./filter_editor', () => ({ + JoinEditor: () => { + return (
    mockFilterEditor
    ); + } +})); + jest.mock('./flyout_footer', () => ({ FlyoutFooter: () => { return (
    mockFlyoutFooter
    ); @@ -54,6 +60,7 @@ const mockLayer = { ]; }, isJoinable: () => { return true; }, + supportsElasticsearchFilters: () => { return false; }, getLayerTypeIconName: () => { return 'vector'; }, }; diff --git a/x-pack/plugins/maps/public/shared/layers/heatmap_layer.js b/x-pack/plugins/maps/public/shared/layers/heatmap_layer.js index 5bcfafcb2650e..93323f7c96465 100644 --- a/x-pack/plugins/maps/public/shared/layers/heatmap_layer.js +++ b/x-pack/plugins/maps/public/shared/layers/heatmap_layer.js @@ -106,8 +106,9 @@ export class HeatmapLayer extends AbstractLayer { mbMap.setLayerZoomRange(mbLayerId, this._descriptor.minZoom, this._descriptor.maxZoom); } - async getBounds(filters) { - return await this._source.getBoundsForFilters(filters); + async getBounds(dataFilters) { + const searchFilters = this._getSearchFilters(dataFilters); + return await this._source.getBoundsForFilters(searchFilters); } async syncData({ startLoading, stopLoading, onLoadError, dataFilters }) { @@ -119,45 +120,52 @@ export class HeatmapLayer extends AbstractLayer { return; } + const searchFilters = this._getSearchFilters(dataFilters); + const sourceDataRequest = this.getSourceDataRequest(); const meta = sourceDataRequest ? sourceDataRequest.getMeta() : {}; - const geogridPrecision = this._source.getGeoGridPrecision(dataFilters.zoom); - const isSamePrecision = meta.geogridPrecision === geogridPrecision; + const isSamePrecision = meta.geogridPrecision === searchFilters.geogridPrecision; - const isSameTime = _.isEqual(meta.timeFilters, dataFilters.timeFilters); + const isSameTime = _.isEqual(meta.timeFilters, searchFilters.timeFilters); - const updateDueToRefreshTimer = dataFilters.refreshTimerLastTriggeredAt - && !_.isEqual(meta.refreshTimerLastTriggeredAt, dataFilters.refreshTimerLastTriggeredAt); + const updateDueToRefreshTimer = searchFilters.refreshTimerLastTriggeredAt + && !_.isEqual(meta.refreshTimerLastTriggeredAt, searchFilters.refreshTimerLastTriggeredAt); - const updateDueToExtent = this.updateDueToExtent(this._source, meta, dataFilters); + const updateDueToExtent = this.updateDueToExtent(this._source, meta, searchFilters); - const updateDueToQuery = dataFilters.query - && !_.isEqual(meta.query, dataFilters.query); + const updateDueToQuery = searchFilters.query + && !_.isEqual(meta.query, searchFilters.query); + const updateDueToLayerQuery = searchFilters.layerQuery + && !_.isEqual(meta.layerQuery, searchFilters.layerQuery); - const updateDueToFilters = dataFilters.filters - && !_.isEqual(meta.filters, dataFilters.filters); + const updateDueToFilters = searchFilters.filters + && !_.isEqual(meta.filters, searchFilters.filters); - const metricPropertyKey = this._getPropKeyOfSelectedMetric(); - const updateDueToMetricChange = !_.isEqual(meta.metric, metricPropertyKey); + const updateDueToMetricChange = !_.isEqual(meta.metric, searchFilters.metric); if (isSamePrecision && isSameTime && !updateDueToExtent && !updateDueToRefreshTimer && !updateDueToQuery + && !updateDueToLayerQuery && !updateDueToFilters && !updateDueToMetricChange ) { return; } - const searchFilters = { + await this._fetchNewData({ startLoading, stopLoading, onLoadError, searchFilters }); + } + + _getSearchFilters(dataFilters) { + return { ...dataFilters, - geogridPrecision, - metric: metricPropertyKey + layerQuery: this.getQuery(), + geogridPrecision: this._source.getGeoGridPrecision(dataFilters.zoom), + metric: this._getPropKeyOfSelectedMetric() }; - await this._fetchNewData({ startLoading, stopLoading, onLoadError, searchFilters }); } async _fetchNewData({ startLoading, stopLoading, onLoadError, searchFilters }) { diff --git a/x-pack/plugins/maps/public/shared/layers/layer.js b/x-pack/plugins/maps/public/shared/layers/layer.js index 899177d1008dc..ec3f6ff4ddd37 100644 --- a/x-pack/plugins/maps/public/shared/layers/layer.js +++ b/x-pack/plugins/maps/public/shared/layers/layer.js @@ -54,6 +54,10 @@ export class AbstractLayer { return this._source.isJoinable(); } + supportsElasticsearchFilters() { + return this._source.supportsElasticsearchFilters(); + } + async supportsFitToBounds() { return await this._source.supportsFitToBounds(); } @@ -118,6 +122,10 @@ export class AbstractLayer { return this._descriptor.alpha; } + getQuery() { + return this._descriptor.query; + } + getZoomConfig() { return { minZoom: this._descriptor.minZoom, diff --git a/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/es_geo_grid_source.js index 42fd064e6dfc0..a5f86290bc054 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -194,7 +194,6 @@ export class ESGeoGridSource extends AbstractESSource { } async getGeoJsonPoints(layerName, searchFilters) { - const indexPattern = await this._getIndexPattern(); const searchSource = await this._makeSearchSource(searchFilters, 0); const aggConfigs = new AggConfigs(indexPattern, this._makeAggConfigs(searchFilters.geogridPrecision), aggSchemas.all); diff --git a/x-pack/plugins/maps/public/shared/layers/sources/es_source.js b/x-pack/plugins/maps/public/shared/layers/sources/es_source.js index 0e51ea6154748..8d18594e34cbd 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/es_source.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/es_source.js @@ -37,6 +37,10 @@ export class AbstractESSource extends AbstractVectorSource { return [this._descriptor.indexPatternId]; } + supportsElasticsearchFilters() { + return true; + } + destroy() { this._inspectorAdapters.requests.resetRequest(this._descriptor.id); } @@ -136,7 +140,7 @@ export class AbstractESSource extends AbstractVectorSource { } } - async _makeSearchSource({ buffer, query, timeFilters, filters }, limit) { + async _makeSearchSource(searchFilters, limit) { const indexPattern = await this._getIndexPattern(); const geoField = await this._getGeoField(); const isTimeAware = await this.isTimeAware(); @@ -144,22 +148,30 @@ export class AbstractESSource extends AbstractVectorSource { searchSource.setField('index', indexPattern); searchSource.setField('size', limit); searchSource.setField('filter', () => { - const allFilters = [...filters]; - if (this.isFilterByMapBounds() && buffer) {//buffer can be empty - allFilters.push(createExtentFilter(buffer, geoField.name, geoField.type)); + const allFilters = [...searchFilters.filters]; + if (this.isFilterByMapBounds() && searchFilters.buffer) {//buffer can be empty + allFilters.push(createExtentFilter(searchFilters.buffer, geoField.name, geoField.type)); } if (isTimeAware) { - allFilters.push(timefilter.createFilter(indexPattern, timeFilters)); + allFilters.push(timefilter.createFilter(indexPattern, searchFilters.timeFilters)); } return allFilters; }); - searchSource.setField('query', query); + searchSource.setField('query', searchFilters.query); + + if (searchFilters.layerQuery) { + const layerSearchSource = new SearchSource(); + layerSearchSource.setField('index', indexPattern); + layerSearchSource.setField('query', searchFilters.layerQuery); + searchSource.setParent(layerSearchSource); + } + return searchSource; } - async getBoundsForFilters({ query, timeFilters, filters }) { + async getBoundsForFilters({ layerQuery, query, timeFilters, filters }) { - const searchSource = await this._makeSearchSource({ query, timeFilters, filters }, 0); + const searchSource = await this._makeSearchSource({ layerQuery, query, timeFilters, filters }, 0); const geoField = await this._getGeoField(); const indexPattern = await this._getIndexPattern(); diff --git a/x-pack/plugins/maps/public/shared/layers/sources/source.js b/x-pack/plugins/maps/public/shared/layers/sources/source.js index 664744a635cf6..3145f138cf983 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/source.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/source.js @@ -102,6 +102,10 @@ export class AbstractSource { isJoinable() { return false; } + + supportsElasticsearchFilters() { + return false; + } } diff --git a/x-pack/plugins/maps/public/shared/layers/vector_layer.js b/x-pack/plugins/maps/public/shared/layers/vector_layer.js index 3561fc46e9a51..1d9d97e65079a 100644 --- a/x-pack/plugins/maps/public/shared/layers/vector_layer.js +++ b/x-pack/plugins/maps/public/shared/layers/vector_layer.js @@ -107,9 +107,10 @@ export class VectorLayer extends AbstractLayer { }; } - async getBounds(filters) { + async getBounds(dataFilters) { if (this._source.isBoundsAware()) { - return await this._source.getBoundsForFilters(filters); + const searchFilters = this._getSearchFilters(dataFilters); + return await this._source.getBoundsForFilters(searchFilters); } return this._getBoundsBasedOnData(); } @@ -203,9 +204,11 @@ export class VectorLayer extends AbstractLayer { let updateDueToQuery = false; let updateDueToFilters = false; + let updateDueToLayerQuery = false; if (isQueryAware) { updateDueToQuery = !_.isEqual(meta.query, searchFilters.query); updateDueToFilters = !_.isEqual(meta.filters, searchFilters.filters); + updateDueToLayerQuery = !_.isEqual(meta.layerQuery, searchFilters.layerQuery); } let updateDueToPrecisionChange = false; @@ -221,6 +224,7 @@ export class VectorLayer extends AbstractLayer { && !updateDueToFields && !updateDueToQuery && !updateDueToFilters + && !updateDueToLayerQuery && !updateDueToPrecisionChange; } @@ -283,6 +287,7 @@ export class VectorLayer extends AbstractLayer { ...dataFilters, fieldNames: _.uniq(fieldNames).sort(), geogridPrecision: this._source.getGeoGridPrecision(dataFilters.zoom), + layerQuery: this.getQuery() }; } diff --git a/x-pack/test/functional/apps/maps/es_search_source.js b/x-pack/test/functional/apps/maps/es_search_source.js index a20f411486373..3b4a6fee0f1d7 100644 --- a/x-pack/test/functional/apps/maps/es_search_source.js +++ b/x-pack/test/functional/apps/maps/es_search_source.js @@ -84,6 +84,31 @@ export default function ({ getPageObjects, getService }) { }); }); + describe('layer query', () => { + before(async () => { + await PageObjects.maps.setLayerQuery('logstash', 'machine.os.raw : "ios"'); + }); + + it('should apply layer query to search request', async () => { + await inspector.open(); + await inspector.openInspectorRequestsView(); + const requestStats = await inspector.getTableData(); + const hits = PageObjects.maps.getInspectorStatRowHit(requestStats, 'Hits'); + await inspector.close(); + expect(hits).to.equal('2'); + }); + + it('should apply layer query to fit to bounds', async () => { + // Set view to other side of world so no matching results + await PageObjects.maps.setView(-15, -100, 6); + await PageObjects.maps.clickFitToBounds('logstash'); + const { lat, lon, zoom } = await PageObjects.maps.getView(); + expect(Math.round(lat)).to.equal(42); + expect(Math.round(lon)).to.equal(-102); + expect(Math.round(zoom)).to.equal(5); + }); + }); + describe('filter by extent', () => { it('should handle geo_point filtering with extents that cross antimeridian', async () => { await PageObjects.maps.loadSavedMap('antimeridian points example'); diff --git a/x-pack/test/functional/page_objects/gis_page.js b/x-pack/test/functional/page_objects/gis_page.js index 0f60d619f6d69..bee98a55d59bc 100644 --- a/x-pack/test/functional/page_objects/gis_page.js +++ b/x-pack/test/functional/page_objects/gis_page.js @@ -232,6 +232,19 @@ export function GisPageProvider({ getService, getPageObjects }) { } } + async setLayerQuery(layerName, query) { + await this.openLayerPanel(layerName); + await testSubjects.click('mapLayerPanelOpenFilterEditorButton'); + const filterEditorContainer = await testSubjects.find('mapFilterEditor'); + const queryBarInFilterEditor = await testSubjects.findDescendant('queryInput', filterEditorContainer); + await queryBarInFilterEditor.click(); + const input = await find.activeElement(); + await input.clearValue(); + await input.type(query); + await testSubjects.click('mapFilterEditorSubmitButton'); + await this.waitForLayersToLoad(); + } + async selectVectorSource() { log.debug(`Select vector source`); await testSubjects.click('vectorShapes'); From 9580e1b4cd938383541389ef5d0aa8ea9cc07004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Wed, 27 Mar 2019 16:02:36 +0100 Subject: [PATCH 56/96] [Rollup] Re-enable api integration tests (#33381) --- .../server/client/elasticsearch_rollup.js | 6 ++ .../plugins/rollup/server/routes/api/jobs.js | 12 +++- .../apis/management/rollup/index.js | 3 +- .../apis/management/rollup/rollup.js | 16 +++--- .../management/rollup/rollup.test_helpers.js | 57 +++---------------- 5 files changed, 34 insertions(+), 60 deletions(-) diff --git a/x-pack/plugins/rollup/server/client/elasticsearch_rollup.js b/x-pack/plugins/rollup/server/client/elasticsearch_rollup.js index 2e62e6cff82a3..b6387502abe2f 100644 --- a/x-pack/plugins/rollup/server/client/elasticsearch_rollup.js +++ b/x-pack/plugins/rollup/server/client/elasticsearch_rollup.js @@ -91,6 +91,12 @@ export const elasticsearchJsPlugin = (Client, config, components) => { }); rollup.stopJob = ca({ + params: { + waitForCompletion: { + type: 'boolean', + name: 'wait_for_completion' + } + }, urls: [ { fmt: '/_rollup/job/<%=id%>/_stop', diff --git a/x-pack/plugins/rollup/server/routes/api/jobs.js b/x-pack/plugins/rollup/server/routes/api/jobs.js index ac4ef3731dbfe..24418dae8e43d 100644 --- a/x-pack/plugins/rollup/server/routes/api/jobs.js +++ b/x-pack/plugins/rollup/server/routes/api/jobs.js @@ -75,6 +75,7 @@ export function registerJobsRoute(server) { handler: async (request) => { try { const { jobIds } = request.payload; + const callWithRequest = callWithRequestFactory(server, request); return await Promise.all(jobIds.map(id => callWithRequest('rollup.startJob', { id }))) .then(() => ({ success: true })); @@ -107,9 +108,17 @@ export function registerJobsRoute(server) { handler: async (request) => { try { const { jobIds } = request.payload; + // For our API integration tests we need to wait for the jobs to be stopped + // in order to be able to delete them sequencially. + const { waitForCompletion } = request.query; const callWithRequest = callWithRequestFactory(server, request); - return await Promise.all(jobIds.map(id => callWithRequest('rollup.stopJob', { id }))) + + const stopRollupJob = id => callWithRequest('rollup.stopJob', { id, waitForCompletion: waitForCompletion === 'true' }); + + return await Promise + .all(jobIds.map(stopRollupJob)) .then(() => ({ success: true })); + } catch(err) { if (isEsError(err)) { return wrapEsError(err); @@ -129,6 +138,7 @@ export function registerJobsRoute(server) { handler: async (request) => { try { const { jobIds } = request.payload; + const callWithRequest = callWithRequestFactory(server, request); return await Promise.all(jobIds.map(id => callWithRequest('rollup.deleteJob', { id }))) .then(() => ({ success: true })); diff --git a/x-pack/test/api_integration/apis/management/rollup/index.js b/x-pack/test/api_integration/apis/management/rollup/index.js index ee0641ce4b4bf..3c55ce6a7a705 100644 --- a/x-pack/test/api_integration/apis/management/rollup/index.js +++ b/x-pack/test/api_integration/apis/management/rollup/index.js @@ -5,8 +5,7 @@ */ export default function ({ loadTestFile }) { - // FLAKY: https://github.com/elastic/kibana/issues/33217 - describe.skip('rollup', () => { + describe('rollup', () => { loadTestFile(require.resolve('./rollup')); loadTestFile(require.resolve('./index_patterns_extensions')); loadTestFile(require.resolve('./rollup_search')); diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup.js b/x-pack/test/api_integration/apis/management/rollup/rollup.js index 64f958e95dd57..fecaf548709bd 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup.js @@ -16,6 +16,7 @@ export default function ({ getService }) { const { createIndexWithMappings, getJobPayload, + loadJobs, createJob, deleteJob, startJob, @@ -77,9 +78,7 @@ export default function ({ getService }) { describe('crud', () => { describe('list', () => { it('should return an empty array when there are no jobs', async () => { - const { body } = await supertest - .get(`${API_BASE_PATH}/jobs`) - .expect(200); + const { body } = await loadJobs().expect(200); expect(body).to.eql({ jobs: [] }); }); @@ -117,7 +116,7 @@ export default function ({ getService }) { const payload = getJobPayload(indexName); await createJob(payload); - const { body: { jobs } } = await supertest.get(`${API_BASE_PATH}/jobs`); + const { body: { jobs } } = await loadJobs(); const job = jobs.find(job => job.config.id === payload.job.id); expect(job).not.be(undefined); @@ -193,7 +192,8 @@ export default function ({ getService }) { await createJob(payload); }); - it('should delete a job that was created', async () => { + it('should delete a job that has been stopped', async () => { + await stopJob(jobId); const { body } = await deleteJob(jobId).expect(200); expect(body).to.eql({ success: true }); }); @@ -215,7 +215,7 @@ export default function ({ getService }) { const payload = getJobPayload(indexName); await createJob(payload); - const { body: { jobs } } = await supertest.get(`${API_BASE_PATH}/jobs`); + const { body: { jobs } } = await loadJobs(); job = jobs.find(job => job.config.id === payload.job.id); }); @@ -228,7 +228,7 @@ export default function ({ getService }) { // Fetch the job to make sure it has been started const jobId = job.config.id; - const { body: { jobs } } = await supertest.get(`${API_BASE_PATH}/jobs`); + const { body: { jobs } } = await loadJobs(); job = jobs.find(job => job.config.id === jobId); expect(job.status.job_state).to.eql('started'); }); @@ -255,7 +255,7 @@ export default function ({ getService }) { expect(body).to.eql({ success: true }); // Fetch the job to make sure it has been stopped - const { body: { jobs } } = await supertest.get(`${API_BASE_PATH}/jobs`); + const { body: { jobs } } = await loadJobs(); const job = jobs.find(job => job.config.id === jobId); expect(job.status.job_state).to.eql('stopped'); }); diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup.test_helpers.js b/x-pack/test/api_integration/apis/management/rollup/rollup.test_helpers.js index cee70461a7bd0..3397bef1dbdaa 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup.test_helpers.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup.test_helpers.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { initElasticsearchIndicesHelpers, getRandomString, wait } from './lib'; +import { initElasticsearchIndicesHelpers, getRandomString } from './lib'; import { API_BASE_PATH, ROLLUP_INDEX_NAME, INDEX_TO_ROLLUP_MAPPINGS } from './constants'; const jobsCreated = []; @@ -81,63 +81,21 @@ export const registerHelpers = ({ supertest, es }) => { const jobIds = Array.isArray(ids) ? ids : [ids]; return supertest - .post(`${API_BASE_PATH}/stop`) + .post(`${API_BASE_PATH}/stop?waitForCompletion=true`) .set('kbn-xsrf', 'xxx') .send({ jobIds }); }; const loadJobs = () => supertest.get(`${API_BASE_PATH}/jobs`); - const waitForJobsToStop = (attempt = 0) => ( + const stopAllJobs = () => ( loadJobs() .then(async ({ body: { jobs } }) => { - const jobBeingStopped = jobs.filter(job => job.status.job_state !== 'stopped' && job.status.job_state !== 'started'); + const jobIds = jobs.map(job => job.config.id); - if (!jobBeingStopped.length) { - return; - } - - if (attempt < 3 && jobBeingStopped.length) { - await wait(500); - return waitForJobsToStop(++attempt); - } + await stopJob(jobIds); - throw new Error('Error while waiting for Rollup Jobs to stop'); - })); - - const stopAllJobStarted = (jobIds = jobsStarted, attempt = 0) => ( - stopJob(jobIds) - .then(waitForJobsToStop) - .then(loadJobs) - .then(({ body: { jobs } }) => { - // We make sure that there are no more jobs started - // as trying to delete a job that is started will throw an exception - const jobsStillStarted = jobs.filter(job => job.status.job_state === 'started').map(job => job.config.id); - - if (jobsStillStarted.length && attempt < 3) { - return stopAllJobStarted(jobsStillStarted, ++attempt); - } else if(jobsStillStarted.length) { - throw new Error('Error trying to stop jobs started'); - } - }) - ); - - const deleteJobsCreated = (ids = jobsCreated, attempt = 0) => ( - deleteJob(ids) - .then((response) => { - if (response.status !== 200 && response.status !== 404) { - throw response; - } - }) - .then(loadJobs) - .then(({ body: { jobs } }) => { - if (jobs.length && attempt < 3) { - // There are still some jobs left to delete. - // Call recursively until all rollup jobs are removed. - return deleteJobsCreated(jobs.map(job => job.config.id), ++attempt); - } else if (jobs.length) { - throw new Error('Error trying to delete Jobs created'); - } + return jobIds; }) ); @@ -155,7 +113,7 @@ export const registerHelpers = ({ supertest, es }) => { const cleanUp = () => ( Promise.all([ deleteAllIndices(), - stopAllJobStarted().then(deleteJobsCreated), + stopAllJobs().then(deleteJob), deleteIndicesGeneratedByJobs(), ]).catch(err => { console.log('ERROR cleaning up!'); @@ -166,6 +124,7 @@ export const registerHelpers = ({ supertest, es }) => { return { createIndexWithMappings, getJobPayload, + loadJobs, createJob, deleteJob, startJob, From 1eada2a7ae7e0ca99a22bcef38ab2cb11c567c69 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 27 Mar 2019 15:16:00 +0000 Subject: [PATCH 57/96] chore(NA): regex path support for windows on babel register ignore patterns. (#33946) --- src/setup_node_env/babel_register/register.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/setup_node_env/babel_register/register.js b/src/setup_node_env/babel_register/register.js index 37e39d4685cac..217dc25a66c5c 100644 --- a/src/setup_node_env/babel_register/register.js +++ b/src/setup_node_env/babel_register/register.js @@ -27,8 +27,8 @@ if (!process.env.BABEL_CACHE_PATH) { // paths that @babel/register should ignore var ignore = [ - /\/bower_components\//, - /\/kbn-pm\/dist\//, + /[\/\\]bower_components[\/\\]/, + /[\/\\]kbn-pm[\/\\]dist[\/\\]/, // TODO: remove this and just transpile plugins at build time, but // has tricky edge cases that will probably require better eslint @@ -39,10 +39,10 @@ var ignore = [ // ignore paths matching `/node_modules/{a}/{b}`, unless `a` // is `x-pack` and `b` is not `node_modules` - /\/node_modules\/(?!x-pack\/(?!node_modules)([^\/]+))([^\/]+\/[^\/]+)/, + /[\/\\]node_modules[\/\\](?!x-pack[\/\\](?!node_modules)([^\/\\]+))([^\/\\]+[\/\\][^\/\\]+)/, // ignore paths matching `/canvas/canvas_plugin/` - /\/canvas\/canvas_plugin\//, + /[\/\\]canvas[\/\\]canvas_plugin[\/\\]/, ]; if (global.__BUILT_WITH_BABEL__) { @@ -60,7 +60,7 @@ if (global.__BUILT_WITH_BABEL__) { // ignore any path in the packages, unless it is in the package's // root `src` directory, in any test or __tests__ directory, or it // ends with .test.js, .test.ts, or .test.tsx - /\/packages\/(eslint-|kbn-)[^\/]+\/(?!src\/.*|(.+\/)?(test|__tests__)\/.+|.+\.test\.(js|ts|tsx)$)(.+$)/ + /[\/\\]packages[\/\\](eslint-|kbn-)[^\/\\]+[\/\\](?!src[\/\\].*|(.+[\/\\])?(test|__tests__)[\/\\].+|.+\.test\.(js|ts|tsx)$)(.+$)/ ); } From b7fcc7b0e6cd0e00c8ca994ff459bff39053f61c Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Wed, 27 Mar 2019 10:36:47 -0700 Subject: [PATCH 58/96] [DOCS] Remove out-dated link (#33980) --- docs/setup/docker.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/setup/docker.asciidoc b/docs/setup/docker.asciidoc index a6a1b0ba9915e..0827cf5c73009 100644 --- a/docs/setup/docker.asciidoc +++ b/docs/setup/docker.asciidoc @@ -96,7 +96,7 @@ Some example translations are shown here: `KIBANA_DEFAULTAPPID`:: `kibana.defaultAppId` `XPACK_MONITORING_ENABLED`:: `xpack.monitoring.enabled` -In general, any setting listed in <> or <> can be +In general, any setting listed in <> can be configured with this technique. These variables can be set with +docker-compose+ like this: From 4d1d3d69ae6e20821984089a7d3d376920fd4d7d Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 27 Mar 2019 11:47:27 -0600 Subject: [PATCH 59/96] skip failing maps application tests (#33977) --- x-pack/test/functional/apps/maps/es_search_source.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional/apps/maps/es_search_source.js b/x-pack/test/functional/apps/maps/es_search_source.js index 3b4a6fee0f1d7..a5f36157ddc87 100644 --- a/x-pack/test/functional/apps/maps/es_search_source.js +++ b/x-pack/test/functional/apps/maps/es_search_source.js @@ -73,7 +73,7 @@ export default function ({ getPageObjects, getService }) { expect(beforeQueryRefreshTimestamp).not.to.equal(afterQueryRefreshTimestamp); }); - it('should apply query to fit to bounds', async () => { + it.skip('should apply query to fit to bounds', async () => { // Set view to other side of world so no matching results await PageObjects.maps.setView(-15, -100, 6); await PageObjects.maps.clickFitToBounds('logstash'); @@ -98,7 +98,7 @@ export default function ({ getPageObjects, getService }) { expect(hits).to.equal('2'); }); - it('should apply layer query to fit to bounds', async () => { + it.skip('should apply layer query to fit to bounds', async () => { // Set view to other side of world so no matching results await PageObjects.maps.setView(-15, -100, 6); await PageObjects.maps.clickFitToBounds('logstash'); From 68a57affaa05b4d86250b60158f0517f41dd58f1 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Wed, 27 Mar 2019 10:50:56 -0700 Subject: [PATCH 60/96] chore: remove the old element ast clearing code (#33905) should no longer be needed, this was changed over a year ago --- x-pack/plugins/canvas/public/state/reducers/elements.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/x-pack/plugins/canvas/public/state/reducers/elements.js b/x-pack/plugins/canvas/public/state/reducers/elements.js index cc62a202a9882..f4d4fe65cf448 100644 --- a/x-pack/plugins/canvas/public/state/reducers/elements.js +++ b/x-pack/plugins/canvas/public/state/reducers/elements.js @@ -36,11 +36,7 @@ function assignNodeProperties(workpadState, pageId, nodeId, props) { return workpadState; } - // remove any AST value from the element caused by https://github.com/elastic/kibana-canvas/issues/260 - // TODO: remove this after a bit of time - const cleanWorkpadState = del(workpadState, nodesPath.concat([nodeIndex, 'ast'])); - - return assign(cleanWorkpadState, nodesPath.concat(nodeIndex), props); + return assign(workpadState, nodesPath.concat(nodeIndex), props); } function moveNodeLayer(workpadState, pageId, nodeId, movement, location) { From 4fac5fc899e70b28bd03af4b8f7ef9a70c91f6c5 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 27 Mar 2019 11:12:52 -0700 Subject: [PATCH 61/96] Revert "[TSVB] markdown variables (#33324)" This reverts commit 412c9d843e5534137aa0b4152edac1146f5fe679. --- .../apps/visualize/_tsvb_markdown.ts | 65 ++----------------- .../page_objects/visual_builder_page.ts | 30 +-------- test/functional/services/browser.js | 14 ++-- test/functional/services/remote/webdriver.ts | 1 + 4 files changed, 14 insertions(+), 96 deletions(-) diff --git a/test/functional/apps/visualize/_tsvb_markdown.ts b/test/functional/apps/visualize/_tsvb_markdown.ts index 47a5e68e68f39..3e62eba78a528 100644 --- a/test/functional/apps/visualize/_tsvb_markdown.ts +++ b/test/functional/apps/visualize/_tsvb_markdown.ts @@ -22,20 +22,11 @@ import { FtrProviderContext } from '../../ftr_provider_context'; // tslint:disable-next-line:no-default-export export default function({ getPageObjects }: FtrProviderContext) { - const { visualBuilder, timePicker } = getPageObjects(['visualBuilder', 'timePicker']); - - async function cleanupMarkdownData(variableName: 'variable' | 'label', checkedValue: string) { - await visualBuilder.markdownSwitchSubTab('data'); - await visualBuilder.setMarkdownDataVariable('', variableName); - - await visualBuilder.markdownSwitchSubTab('markdown'); - const rerenderedTable = await visualBuilder.getMarkdownTableVariables(); - rerenderedTable.forEach(row => { - variableName === 'label' - ? expect(row.key).to.include.string(checkedValue) - : expect(row.key).to.not.include.string(checkedValue); - }); - } + const { visualBuilder, timePicker } = getPageObjects([ + 'visualBuilder', + 'timePicker', + 'visualize', + ]); describe('visual builder', function describeIndexTests() { describe('markdown', () => { @@ -80,52 +71,6 @@ export default function({ getPageObjects }: FtrProviderContext) { const markdownText = await visualBuilder.getMarkdownText(); expect(markdownText).to.be(expectedRenderer); }); - - it('should change label name', async () => { - const BASE_LABEL = 'count'; - const LABEL = 'label'; - await visualBuilder.markdownSwitchSubTab('data'); - - await visualBuilder.setMarkdownDataVariable(LABEL, LABEL); - - await visualBuilder.markdownSwitchSubTab('markdown'); - const table = await visualBuilder.getMarkdownTableVariables(); - table.forEach(row => { - expect(row.key).to.contain(LABEL); - }); - await cleanupMarkdownData(LABEL, BASE_LABEL); - }); - - it('should change variable name', async () => { - const VARIABLE = 'variable'; - await visualBuilder.markdownSwitchSubTab('data'); - await visualBuilder.setMarkdownDataVariable(VARIABLE, VARIABLE); - await visualBuilder.markdownSwitchSubTab('markdown'); - const table = await visualBuilder.getMarkdownTableVariables(); - - table.forEach((row, index) => { - // exception: last index for variable is always: {{count.label}} - index === table.length - 1 - ? expect(row.key).to.not.include.string(VARIABLE) - : expect(row.key).to.include.string(VARIABLE); - }); - - await cleanupMarkdownData(VARIABLE, VARIABLE); - }); - - it('should render markdown table', async () => { - const TABLE = - '| raw | formatted |\n|-|-|\n| {{count.last.raw}} | {{count.last.formatted}} |'; - const DATA = '46'; - - await visualBuilder.enterMarkdown(TABLE); - const text = await visualBuilder.getMarkdownText(); - const tableValues = text.split('\n').map(row => row.split(' '))[1]; // [46, 46] - - tableValues.forEach(value => { - expect(value).to.be.equal(DATA); - }); - }); }); }); } diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 4224af0af8e49..bd2f219486bf5 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -83,7 +83,7 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro await input.pressKeys(browser.keys.BACK_SPACE); // Delete all content } - public async getMarkdownText(): Promise { + public async getMarkdownText() { const el = await find.byCssSelector('.tvbEditorVisualization'); const text = await el.getVisibleText(); return text; @@ -156,34 +156,6 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro await element.click(); } - /** - * setting label for markdown visualization - * - * @param {string} variableName - * @param type - * @memberof VisualBuilderPage - */ - public async setMarkdownDataVariable(variableName: string, type: 'variable' | 'label') { - const SELECTOR = type === 'label' ? '[placeholder="Label"]' : '[placeholder="Variable name"]'; - const prevRenderingCount = await PageObjects.visualize.getVisualizationRenderingCount(); - if (variableName) { - await find.setValue(SELECTOR, variableName); - } else { - const input = await find.byCssSelector(SELECTOR); - if (process.platform === 'darwin') { - // Mac workaround - for (let i = 0; i <= type.length; i++) { - await input.pressKeys(browser.keys.BACK_SPACE); - } - } else { - await input.pressKeys([browser.keys.CONTROL, 'a']); // Select all for everything else - await input.pressKeys(browser.keys.NULL); // Release modifier keys - await input.pressKeys(browser.keys.BACK_SPACE); // Delete all content - } - } - await PageObjects.visualize.waitForRenderingCount(prevRenderingCount + 1); - } - public async clickSeriesOption(nth = 0) { const el = await testSubjects.findAll('seriesOptions'); await el[nth].click(); diff --git a/test/functional/services/browser.js b/test/functional/services/browser.js index 55322b386e8f2..7f7e26de888bd 100644 --- a/test/functional/services/browser.js +++ b/test/functional/services/browser.js @@ -22,11 +22,11 @@ import { cloneDeep } from 'lodash'; import { modifyUrl } from '../../../src/core/utils'; import { WebElementWrapper } from './lib/web_element_wrapper'; - export async function BrowserProvider({ getService }) { const { driver, Key, LegacyActionSequence } = await getService('__webdriver__').init(); class BrowserService { + /** * Keyboard events */ @@ -121,8 +121,8 @@ export async function BrowserProvider({ getService }) { async dragAndDrop(from, to) { let _from; let _to; - const _fromOffset = from.offset ? { x: from.offset.x || 0, y: from.offset.y || 0 } : { x: 0, y: 0 }; - const _toOffset = to.offset ? { x: to.offset.x || 0, y: to.offset.y || 0 } : { x: 0, y: 0 }; + const _fromOffset = (from.offset) ? { x: from.offset.x || 0, y: from.offset.y || 0 } : { x: 0, y: 0 }; + const _toOffset = (to.offset) ? { x: to.offset.x || 0, y: to.offset.y || 0 } : { x: 0, y: 0 }; if (from.location instanceof WebElementWrapper) { _from = from.location._webElement; @@ -230,9 +230,9 @@ export async function BrowserProvider({ getService }) { * @return {Promise} */ async getLogsFor(...args) { - // The logs endpoint has not been defined in W3C Spec browsers other than Chrome don't have access to this endpoint. - // See: https://github.com/w3c/webdriver/issues/406 - // See: https://w3c.github.io/webdriver/#endpoints + //The logs endpoint has not been defined in W3C Spec browsers other than Chrome don't have access to this endpoint. + //See: https://github.com/w3c/webdriver/issues/406 + //See: https://w3c.github.io/webdriver/#endpoints if (driver.executor_.w3c === true) { return []; } else { @@ -358,5 +358,5 @@ export async function BrowserProvider({ getService }) { } } - return new BrowserService(); + return new BrowserService(); } diff --git a/test/functional/services/remote/webdriver.ts b/test/functional/services/remote/webdriver.ts index 8bc4a2cb31db9..0be87382c94a0 100644 --- a/test/functional/services/remote/webdriver.ts +++ b/test/functional/services/remote/webdriver.ts @@ -22,6 +22,7 @@ import { delay } from 'bluebird'; import chromeDriver from 'chromedriver'; // @ts-ignore types not available import geckoDriver from 'geckodriver'; + // @ts-ignore types for 4.0 not available yet import { Builder, By, Key, logging, until } from 'selenium-webdriver'; // @ts-ignore types not available From 2882d2853f57a2b629fd9ea1ec851cc4196114ba Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Wed, 27 Mar 2019 19:43:01 +0100 Subject: [PATCH 62/96] [ML] Fixes check to determine whether telemetry is enabled. (#33975) --- .../plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts | 4 +--- x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts index 2193e26a7e1fb..9a0c3608a893c 100644 --- a/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts +++ b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts @@ -120,9 +120,7 @@ describe('ml_telemetry', () => { } return { attributes: { - telemetry: { - enabled: telemetryEnabled, - }, + enabled: telemetryEnabled, }, }; case 'ml-telemetry': diff --git a/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts index 2ff2ae1ed8738..fef0bb2e7617c 100644 --- a/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts +++ b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts @@ -47,7 +47,7 @@ export async function incrementFileDataVisualizerIndexCreationCount(server: Serv try { const { attributes } = await savedObjectsClient.get('telemetry', 'telemetry'); - if (attributes.telemetry.enabled === false) { + if (attributes.enabled === false) { return; } } catch (error) { From 64e77b3a3e6e1e2bfc42bd0919359ab0c9df6190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Wed, 27 Mar 2019 19:44:10 +0100 Subject: [PATCH 63/96] [APM] Fix schema issues (#33833) --- x-pack/plugins/apm/typings/es_schemas/raw/APMBaseDoc.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/APMBaseDoc.ts b/x-pack/plugins/apm/typings/es_schemas/raw/APMBaseDoc.ts index 1717156d52cfd..e6cec18e8a0dd 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/APMBaseDoc.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/APMBaseDoc.ts @@ -6,17 +6,16 @@ // all documents types extend APMBaseDoc and inherit all properties export interface APMBaseDoc { - '@metadata': unknown; '@timestamp': string; agent: { name: string; version: string; }; - observer: unknown; timestamp: { us: number }; parent?: { id: string }; // parent ID is not available on root transactions trace?: { id: string }; labels?: { [key: string]: string | number | boolean; }; + [key: string]: unknown; } From d3e8ee317df7380e85cd35e9e3f8e9be6d96dc08 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Wed, 27 Mar 2019 13:23:32 -0700 Subject: [PATCH 64/96] [DOCS] Removes abbrevtitles from parts (#34002) --- docs/CHANGELOG.asciidoc | 5 +---- docs/graph/index.asciidoc | 4 +--- docs/release-notes/highlights.asciidoc | 5 +---- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index cac755cad970f..d0c19f8628361 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -1,8 +1,5 @@ [[release-notes]] -= {kib} Release Notes -++++ -Release Notes -++++ += Release Notes [partintro] -- diff --git a/docs/graph/index.asciidoc b/docs/graph/index.asciidoc index b60bd1bc78d12..dca248257e4e0 100644 --- a/docs/graph/index.asciidoc +++ b/docs/graph/index.asciidoc @@ -1,9 +1,6 @@ [role="xpack"] [[xpack-graph]] = Graphing Connections in Your Data -++++ -Graph -++++ [partintro] -- @@ -66,6 +63,7 @@ multi-node clusters and scales with your Elasticsearch deployment. Advanced options let you control how your data is sampled and summarized. You can also set timeouts to prevent graph queries from adversely affecting the cluster. + -- include::getting-started.asciidoc[] diff --git a/docs/release-notes/highlights.asciidoc b/docs/release-notes/highlights.asciidoc index f490ca2618300..a8e9955964687 100644 --- a/docs/release-notes/highlights.asciidoc +++ b/docs/release-notes/highlights.asciidoc @@ -1,8 +1,5 @@ [[release-highlights]] -= {kib} Release Highlights -++++ -Release Highlights -++++ += Release Highlights [partintro] -- From 07ad8fdbabac4866164b5b643559d0aebe14b44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Wed, 27 Mar 2019 21:34:48 +0100 Subject: [PATCH 65/96] Fix babel initialization for graphql type generation (#33962) This restores the functionality of the graphql type generation scripts after #33093. In particular, it properly sets up the babel import hook so schemata can once more be imported from `.ts/.tsx` files. --- x-pack/plugins/infra/scripts/generate_types_from_graphql.js | 2 ++ x-pack/plugins/uptime/scripts/infer_graphql_types.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/x-pack/plugins/infra/scripts/generate_types_from_graphql.js b/x-pack/plugins/infra/scripts/generate_types_from_graphql.js index caeb73c3bf797..aec5ff6da99ce 100644 --- a/x-pack/plugins/infra/scripts/generate_types_from_graphql.js +++ b/x-pack/plugins/infra/scripts/generate_types_from_graphql.js @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +require('../../../../src/setup_node_env'); + const { join, resolve } = require('path'); // eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved const { generate } = require('graphql-code-generator'); diff --git a/x-pack/plugins/uptime/scripts/infer_graphql_types.js b/x-pack/plugins/uptime/scripts/infer_graphql_types.js index 104fd5b66b5d6..b821fbde4084e 100644 --- a/x-pack/plugins/uptime/scripts/infer_graphql_types.js +++ b/x-pack/plugins/uptime/scripts/infer_graphql_types.js @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +require('../../../../src/setup_node_env'); + const { resolve } = require('path'); // eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved const { generate } = require('graphql-code-generator'); From 049723da8a298561384f2f9e3272bbb3cf3127d6 Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Wed, 27 Mar 2019 15:35:16 -0500 Subject: [PATCH 66/96] Fix missed `start` -> `setup` renames (#33967) --- src/legacy/server/kbn_server.d.ts | 2 +- src/legacy/ui/public/new_platform/new_platform.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts index ad4d3b92c5c66..3bb885dbee756 100644 --- a/src/legacy/server/kbn_server.d.ts +++ b/src/legacy/server/kbn_server.d.ts @@ -62,7 +62,7 @@ type KbnMixinFunc = (kbnServer: KbnServer, server: Server, config: any) => Promi type Unpromise = T extends Promise ? U : T; export default class KbnServer { public readonly newPlatform: { - start: { + setup: { core: { elasticsearch: ElasticsearchServiceSetup; }; diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts index 7c6e5380cea1a..d6ea22e4e703f 100644 --- a/src/legacy/ui/public/new_platform/new_platform.ts +++ b/src/legacy/ui/public/new_platform/new_platform.ts @@ -38,18 +38,18 @@ interface CoreSetup { } const runtimeContext = { - start: { + setup: { core: null as CoreSetup | null, plugins: {}, }, }; export function __newPlatformInit__(core: CoreSetup) { - if (runtimeContext.start.core) { + if (runtimeContext.setup.core) { throw new Error('New platform core api was already initialized'); } - runtimeContext.start.core = core; + runtimeContext.setup.core = core; } export function getNewPlatform() { From 3acebd9d57c317c83003285a796d8415be3cbcb3 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Wed, 27 Mar 2019 15:49:52 -0500 Subject: [PATCH 67/96] Upgrade EUI to 9.6.0 (#33873) * eui to 9.6.0 * update snapshots related to onClick --- package.json | 2 +- .../inspector_panel.test.js.snap | 5 +- .../plugins/kbn_tp_run_pipeline/package.json | 2 +- .../kbn_tp_custom_visualizations/package.json | 2 +- .../kbn_tp_sample_panel_action/package.json | 4 +- .../kbn_tp_visualize_embedding/package.json | 2 +- x-pack/package.json | 2 +- .../__test__/__snapshots__/List.test.tsx.snap | 20 +++++-- .../font_picker.examples.storyshot | 10 +++- .../extend_index_management.test.js.snap | 5 +- .../telemetry_opt_in.test.js.snap | 5 +- .../report_info_button.test.tsx.snap | 16 +++-- yarn.lock | 60 ++----------------- 13 files changed, 59 insertions(+), 76 deletions(-) diff --git a/package.json b/package.json index 5abfcdd651a83..0047641cc184b 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "@babel/polyfill": "^7.2.5", "@babel/register": "^7.0.0", "@elastic/datemath": "5.0.2", - "@elastic/eui": "9.5.0", + "@elastic/eui": "9.6.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.3.2", diff --git a/src/legacy/ui/public/inspector/ui/__snapshots__/inspector_panel.test.js.snap b/src/legacy/ui/public/inspector/ui/__snapshots__/inspector_panel.test.js.snap index 9d5e8fe0725a0..aa16a91a4c9ad 100644 --- a/src/legacy/ui/public/inspector/ui/__snapshots__/inspector_panel.test.js.snap +++ b/src/legacy/ui/public/inspector/ui/__snapshots__/inspector_panel.test.js.snap @@ -242,8 +242,11 @@ exports[`InspectorPanel should render as expected 1`] = `
    List should render empty state 1`] = `
    List should render empty state 1`] = `
    List should render with data 1`] = `
    List should render with data 1`] = `
    Date: Wed, 27 Mar 2019 14:14:01 -0700 Subject: [PATCH 68/96] Remove segmented fetch (#33453) * Remove segmented fetch * Fix namespace * Remove unused translations --- docs/management/advanced-options.asciidoc | 3 - .../public/discover/__tests__/hit_sort_fn.js | 93 ----- .../kibana/public/discover/_hit_sort_fn.js | 82 ----- .../public/discover/controllers/discover.js | 238 ++++-------- .../kibana/public/discover/index.html | 2 - .../kibana/ui_setting_defaults.js | 13 - .../segmented_search_request.create_queue.js | 82 ----- ...egmented_search_request.index_selection.js | 148 -------- .../__tests__/segmented_search_request.js | 88 ----- .../segmented_search_request.size_picking.js | 70 ---- .../request/segmented_search_request/index.js | 20 - .../segmented_handle.js | 59 --- .../segmented_search_request.js | 346 ------------------ .../courier/search_source/search_source.js | 22 -- .../translations/translations/zh-CN.json | 6 +- 15 files changed, 69 insertions(+), 1203 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js delete mode 100644 src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/index.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 78b6922927c17..50a229f0b2dd4 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -41,9 +41,6 @@ working on big documents. Set this property to `false` to disable highlighting. `doc_table:hideTimeColumn`:: Hide the 'Time' column in Discover and in all Saved Searches on Dashboards. `search:includeFrozen`:: Will include {ref}/frozen-indices.html[frozen indices] in results if enabled. Searching through frozen indices might increase the search time. -`courier:maxSegmentCount`:: Kibana splits requests in the Discover app into segments to limit the size of requests sent to -the Elasticsearch cluster. This setting constrains the length of the segment list. Long segment lists can significantly -increase request processing time. `courier:ignoreFilterIfFieldNotInIndex`:: Set this property to `true` to skip filters that apply to fields that don't exist in a visualization's index. Useful when dashboards consist of visualizations from multiple index patterns. `courier:maxConcurrentShardRequests`:: Controls the {ref}/search-multi-search.html[max_concurrent_shard_requests] setting used for _msearch requests sent by Kibana. Set to 0 to disable this config and use the Elasticsearch default. `fields:popularLimit`:: This setting governs how many of the top most popular fields are shown. diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js deleted file mode 100644 index 3c7e1e83688dc..0000000000000 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js +++ /dev/null @@ -1,93 +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 _ from 'lodash'; -import ngMock from 'ng_mock'; -import expect from '@kbn/expect'; -import PluginsKibanaDiscoverHitSortFnProvider from '../_hit_sort_fn'; - -describe('hit sort function', function () { - let createHitSortFn; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - createHitSortFn = Private(PluginsKibanaDiscoverHitSortFnProvider); - })); - - - const runSortTest = function (dir, sortOpts) { - const groupSize = _.random(10, 30); - const total = sortOpts.length * groupSize; - - sortOpts = sortOpts.map(function (opt) { - if (Array.isArray(opt)) return opt; - else return [opt]; - }); - const sortOptLength = sortOpts.length; - - const hits = _.times(total, function (i) { - return { - _source: {}, - sort: sortOpts[i % sortOptLength] - }; - }); - - hits.sort(createHitSortFn(dir)) - .forEach(function (hit, i) { - const group = Math.floor(i / groupSize); - expect(hit.sort).to.eql(sortOpts[group]); - }); - }; - - - it('sorts a list of hits in ascending order', function () { - runSortTest('asc', [200, 404, 500]); - }); - - it('sorts a list of hits in descending order', function () { - runSortTest('desc', [10, 3, 1]); - }); - - it('breaks ties in ascending order', function () { - runSortTest('asc', [ - [ 'apache', 200, 'facebook.com' ], - [ 'apache', 200, 'twitter.com' ], - [ 'apache', 301, 'facebook.com' ], - [ 'apache', 301, 'twitter.com' ], - [ 'nginx', 200, 'facebook.com' ], - [ 'nginx', 200, 'twitter.com' ], - [ 'nginx', 301, 'facebook.com' ], - [ 'nginx', 301, 'twitter.com' ] - ]); - }); - - it('breaks ties in descending order', function () { - runSortTest('desc', [ - [ 'nginx', 301, 'twitter.com' ], - [ 'nginx', 301, 'facebook.com' ], - [ 'nginx', 200, 'twitter.com' ], - [ 'nginx', 200, 'facebook.com' ], - [ 'apache', 301, 'twitter.com' ], - [ 'apache', 301, 'facebook.com' ], - [ 'apache', 200, 'twitter.com' ], - [ 'apache', 200, 'facebook.com' ] - ]); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js b/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js deleted file mode 100644 index c60f13bb76d4f..0000000000000 --- a/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js +++ /dev/null @@ -1,82 +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-default-export -export default function HitSortFnFactory() { - /** - * Creates a sort function that will resort hits based on the value - * es used to sort them. - * - * background: - * When a hit is sorted by elasticsearch, es will write the values that it used - * to sort them into an array at the top level of the hit like so - * - * ``` - * hits: { - * total: x, - * hits: [ - * { - * _id: i, - * _source: {}, - * sort: [ - * // all values used to sort, in the order of precedence - * ] - * } - * ] - * }; - * ``` - * - * @param {[type]} field [description] - * @param {[type]} direction [description] - * @return {[type]} [description] - */ - return function createHitSortFn(direction) { - const descending = (direction === 'desc'); - - return function sortHits(hitA, hitB) { - let bBelowa = null; - - const aSorts = hitA.sort || []; - const bSorts = hitB.sort || []; - - // walk each sort value, and compare until one is different - for (let i = 0; i < bSorts.length; i++) { - const a = aSorts[i]; - const b = bSorts[i]; - - if (a == null || b > a) { - bBelowa = !descending; - break; - } - - if (b < a) { - bBelowa = descending; - break; - } - } - - if (bBelowa !== null) { - return bBelowa ? -1 : 1; - } else { - return 0; - } - - }; - }; -} diff --git a/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js b/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js index 3c8da5dd3ab8f..2eba42eded544 100644 --- a/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js @@ -39,7 +39,6 @@ import { toastNotifications } from 'ui/notify'; import { VisProvider } from 'ui/vis'; import { VislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib'; import { DocTitleProvider } from 'ui/doc_title'; -import PluginsKibanaDiscoverHitSortFnProvider from '../_hit_sort_fn'; import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter'; import { intervalOptions } from 'ui/agg_types/buckets/_interval_options'; import { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; @@ -67,6 +66,12 @@ import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_s import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../breadcrumbs'; import { buildVislibDimensions } from 'ui/visualize/loader/pipeline_helpers/build_pipeline'; +const fetchStatuses = { + UNINITIALIZED: 'uninitialized', + LOADING: 'loading', + COMPLETE: 'complete', +}; + const app = uiModules.get('apps/discover', [ 'kibana/notify', 'kibana/courier', @@ -170,7 +175,6 @@ function discoverController( let visualizeHandler; const Vis = Private(VisProvider); const docTitle = Private(DocTitleProvider); - const HitSortFn = Private(PluginsKibanaDiscoverHitSortFnProvider); const queryFilter = Private(FilterBarQueryFilterProvider); const responseHandler = Private(VislibSeriesResponseHandlerProvider).handler; const filterManager = Private(FilterManagerProvider); @@ -190,6 +194,7 @@ function discoverController( $scope.intervalOptions = intervalOptions; $scope.showInterval = false; $scope.minimumVisibleRows = 50; + $scope.fetchStatus = fetchStatuses.UNINITIALIZED; $scope.intervalEnabled = function (interval) { return interval.val !== 'custom'; @@ -373,18 +378,16 @@ function discoverController( const getFieldCounts = async () => { // the field counts aren't set until we have the data back, // so we wait for the fetch to be done before proceeding - if (!$scope.fetchStatus) { + if ($scope.fetchStatus === fetchStatuses.COMPLETE) { return $scope.fieldCounts; } return await new Promise(resolve => { const unwatch = $scope.$watch('fetchStatus', (newValue) => { - if (newValue) { - return; + if (newValue === fetchStatuses.COMPLETE) { + unwatch(); + resolve($scope.fieldCounts); } - - unwatch(); - resolve($scope.fieldCounts); }); }); }; @@ -567,13 +570,9 @@ function discoverController( if (rows == null && oldRows == null) return status.LOADING; const rowsEmpty = _.isEmpty(rows); - // An undefined fetchStatus means the requests are still being - // prepared to be sent. When all requests are completed, - // fetchStatus is set to null, so it's important that we - // specifically check for undefined to determine a loading status. - const preparingForFetch = _.isUndefined(fetchStatus); + const preparingForFetch = fetchStatus === fetchStatuses.UNINITIALIZED; if (preparingForFetch) return status.LOADING; - else if (rowsEmpty && fetchStatus) return status.LOADING; + else if (rowsEmpty && fetchStatus === fetchStatuses.LOADING) return status.LOADING; else if (!rowsEmpty) return status.READY; else return status.NO_RESULTS; } @@ -662,6 +661,8 @@ function discoverController( .then(setupVisualization) .then(function () { $state.save(); + $scope.fetchStatus = fetchStatuses.LOADING; + logInspectorRequest(); return courier.fetch(); }) .catch(notify.error); @@ -673,176 +674,72 @@ function discoverController( $scope.fetch(); }; - - function handleSegmentedFetch(segmented) { - function flushResponseData() { - $scope.fetchError = undefined; - $scope.hits = 0; - $scope.failures = []; - $scope.rows = []; - $scope.fieldCounts = {}; - } - - if (!$scope.rows) flushResponseData(); - - const sort = $state.sort; - const timeField = $scope.indexPattern.timeFieldName; - - /** - * Basically an emum. - * - * opts: - * "time" - sorted by the timefield - * "non-time" - explicitly sorted by a non-time field, NOT THE SAME AS `sortBy !== "time"` - * "implicit" - no sorting set, NOT THE SAME AS "non-time" - * - * @type {String} - */ - const sortBy = (function () { - if (!Array.isArray(sort)) return 'implicit'; - else if (sort[0] === '_score') return 'implicit'; - else if (sort[0] === timeField) return 'time'; - else return 'non-time'; - }()); - - let sortFn = null; - if (sortBy !== 'implicit') { - sortFn = new HitSortFn(sort[1]); - } - - $scope.updateTime(); - - if (sort[0] === '_score') { - segmented.setMaxSegments(1); - } - - segmented.setDirection(sortBy === 'time' ? (sort[1] || 'desc') : 'desc'); - segmented.setSortFn(sortFn); - segmented.setSize($scope.opts.sampleSize); - - let inspectorRequests = []; - function logResponseInInspector(resp) { - if (inspectorRequests.length > 0) { - const inspectorRequest = inspectorRequests.shift(); - inspectorRequest - .stats(getResponseInspectorStats($scope.searchSource, resp)) - .ok({ json: resp }); - } - } - - // triggered when the status updated - segmented.on('status', function (status) { - $scope.fetchStatus = status; - if (status.complete === 0) { - // starting new segmented search request - inspectorAdapters.requests.reset(); - inspectorRequests = []; - } - - if (status.remaining > 0) { - const inspectorRequest = inspectorAdapters.requests.start( - i18n('kbn.discover.inspectorRequest.segmentFetchCompleteStatusTitle', { - defaultMessage: 'Segment {fetchCompleteStatus}', - values: { - fetchCompleteStatus: $scope.fetchStatus.complete, + function onResults(resp) { + logInspectorResponse(resp); + + if ($scope.opts.timefield) { + const tabifiedData = tabifyAggResponse($scope.vis.aggs, resp); + $scope.searchSource.rawResponse = resp; + Promise + .resolve(buildVislibDimensions($scope.vis, { timeRange: $scope.timeRange, searchSource: $scope.searchSource })) + .then(resp => responseHandler(tabifiedData, resp)) + .then(resp => { + visualizeHandler.render({ + as: 'visualization', + value: { + visType: $scope.vis.type.name, + visData: resp, + visConfig: $scope.vis.params, + params: {}, } - }), - { - description: i18n('kbn.discover.inspectorRequest.segmentFetchCompleteStatusDescription', { - defaultMessage: 'This request queries Elasticsearch to fetch the data for the search.', - }), }); - inspectorRequest.stats(getRequestInspectorStats($scope.searchSource)); - $scope.searchSource.getSearchRequestBody().then(body => { - inspectorRequest.json(body); }); - inspectorRequests.push(inspectorRequest); - } - - }); + } - segmented.on('first', function () { - flushResponseData(); - }); + $scope.hits = resp.hits.total; + $scope.rows = resp.hits.hits; - segmented.on('segment', (resp) => { - logResponseInInspector(resp); - if (resp._shards.failed > 0) { - $scope.failures = _.union($scope.failures, resp._shards.failures); - $scope.failures = _.uniq($scope.failures, false, function (failure) { - return failure.index + failure.shard + failure.reason; - }); - } - }); + // if we haven't counted yet, reset the counts + const counts = $scope.fieldCounts = $scope.fieldCounts || {}; - segmented.on('emptySegment', function (resp) { - logResponseInInspector(resp); + $scope.rows.forEach(hit => { + const fields = Object.keys($scope.indexPattern.flattenHit(hit)); + fields.forEach(fieldName => { + counts[fieldName] = (counts[fieldName] || 0) + 1; + }); }); - segmented.on('mergedSegment', function (merged) { - $scope.mergedEsResp = merged; - - if ($scope.opts.timefield) { - const tabifiedData = tabifyAggResponse($scope.vis.aggs, merged); - $scope.searchSource.rawResponse = merged; - Promise - .resolve(buildVislibDimensions($scope.vis, { timeRange: $scope.timeRange, searchSource: $scope.searchSource })) - .then(resp => responseHandler(tabifiedData, resp)) - .then(resp => { - visualizeHandler.render({ - as: 'visualization', - value: { - visType: $scope.vis.type.name, - visData: resp, - visConfig: $scope.vis.params, - params: {}, - } - }); - }); - } - - $scope.hits = merged.hits.total; - - const indexPattern = $scope.searchSource.getField('index'); - - // the merge rows, use a new array to help watchers - $scope.rows = merged.hits.hits.slice(); + $scope.fetchStatus = fetchStatuses.COMPLETE; - let counts = $scope.fieldCounts; - - // if we haven't counted yet, or need a fresh count because we are sorting, reset the counts - if (!counts || sortFn) counts = $scope.fieldCounts = {}; - - $scope.rows.forEach(function (hit) { - // skip this work if we have already done it - if (hit.$$_counted) return; + return $scope.searchSource.onResults().then(onResults); + } - // when we are sorting results, we need to redo the counts each time because the - // "top 500" may change with each response, so don't mark this as counted - if (!sortFn) hit.$$_counted = true; + let inspectorRequest; - const fields = _.keys(indexPattern.flattenHit(hit)); - let n = fields.length; - let field; - while (field = fields[--n]) { - if (counts[field]) counts[field] += 1; - else counts[field] = 1; - } - }); + function logInspectorRequest() { + inspectorAdapters.requests.reset(); + const title = i18n('kbn.discover.inspectorRequestDataTitle', { + defaultMessage: 'Data', }); - - segmented.on('complete', function () { - if ($scope.fetchStatus.hitCount === 0) { - flushResponseData(); - } - - $scope.fetchStatus = null; + const description = i18n('kbn.discover.inspectorRequestDescription', { + defaultMessage: 'This request queries Elasticsearch to fetch the data for the search.', + }); + inspectorRequest = inspectorAdapters.requests.start(title, { description }); + inspectorRequest.stats(getRequestInspectorStats($scope.searchSource)); + $scope.searchSource.getSearchRequestBody().then(body => { + inspectorRequest.json(body); }); } + function logInspectorResponse(resp) { + inspectorRequest + .stats(getResponseInspectorStats($scope.searchSource, resp)) + .ok({ json: resp }); + } - function beginSegmentedFetch() { - $scope.searchSource.onBeginSegmentedFetch(handleSegmentedFetch) + function startSearching() { + return $scope.searchSource.onResults() + .then(onResults) .catch((error) => { const fetchError = getPainlessError(error); @@ -853,10 +750,11 @@ function discoverController( } // Restart. This enables auto-refresh functionality. - beginSegmentedFetch(); + startSearching(); }); } - beginSegmentedFetch(); + + startSearching(); $scope.updateTime = function () { $scope.timeRange = { diff --git a/src/legacy/core_plugins/kibana/public/discover/index.html b/src/legacy/core_plugins/kibana/public/discover/index.html index ecd6dcf5e6772..4def63c620d49 100644 --- a/src/legacy/core_plugins/kibana/public/discover/index.html +++ b/src/legacy/core_plugins/kibana/public/discover/index.html @@ -101,8 +101,6 @@

    -
    -
    {{fetchStatus.complete}} / {{fetchStatus.total}}
    diff --git a/src/legacy/core_plugins/kibana/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/ui_setting_defaults.js index 55cdc3e38e7f3..00af1aeae26b8 100644 --- a/src/legacy/core_plugins/kibana/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/ui_setting_defaults.js @@ -302,19 +302,6 @@ export function getUiSettingDefaults() { }), category: ['discover'], }, - 'courier:maxSegmentCount': { - name: i18n.translate('kbn.advancedSettings.courier.maxSegmentCountTitle', { - defaultMessage: 'Maximum segment count', - }), - value: 30, - description: i18n.translate('kbn.advancedSettings.courier.maxSegmentCountText', { - defaultMessage: - 'Requests in discover are split into segments to prevent massive requests from being sent to elasticsearch. ' + - 'This setting attempts to prevent the list of segments from getting too long, ' + - 'which might cause requests to take much longer to process.', - }), - category: ['search'], - }, 'courier:ignoreFilterIfFieldNotInIndex': { name: i18n.translate('kbn.advancedSettings.courier.ignoreFilterTitle', { defaultMessage: 'Ignore filter(s)', diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js deleted file mode 100644 index 80f0ce3309a41..0000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js +++ /dev/null @@ -1,82 +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 sinon from 'sinon'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; - -import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source'; - -import { SegmentedSearchRequestProvider } from '../segmented_search_request'; - -describe('SegmentedSearchRequest _createQueue', () => { - let Promise; - let SegmentedSearchRequest; - let MockSource; - - require('test_utils/no_digest_promises').activateForSuite(); - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject((Private, $injector) => { - Promise = $injector.get('Promise'); - SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); - - MockSource = class { - constructor() { - return $injector.invoke(StubbedSearchSourceProvider); - } - }; - })); - - it('manages the req._queueCreated flag', async function () { - const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} }); - req._queueCreated = null; - - const promise = req._createQueue(); - expect(req._queueCreated).to.be(false); - await promise; - expect(req._queueCreated).to.be(true); - }); - - it('relies on indexPattern.toDetailedIndexList to generate queue', async function () { - const searchSource = new MockSource(); - const indexPattern = searchSource.getField('index'); - const indices = [1, 2, 3]; - sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve(indices)); - - const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} }); - const output = await req._createQueue(); - expect(output).to.equal(indices); - }); - - it('tells the index pattern its direction', async function () { - const searchSource = new MockSource(); - const indexPattern = searchSource.getField('index'); - const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} }); - sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve([1, 2, 3])); - - req.setDirection('asc'); - await req._createQueue(); - expect(indexPattern.toDetailedIndexList.lastCall.args[2]).to.be('asc'); - - req.setDirection('desc'); - await req._createQueue(); - expect(indexPattern.toDetailedIndexList.lastCall.args[2]).to.be('desc'); - }); -}); diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js deleted file mode 100644 index 6914e9338028c..0000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js +++ /dev/null @@ -1,148 +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 ngMock from 'ng_mock'; -import expect from '@kbn/expect'; -import { times } from 'lodash'; -import sinon from 'sinon'; - -import HitSortFnProv from 'plugins/kibana/discover/_hit_sort_fn'; -import NoDigestPromises from 'test_utils/no_digest_promises'; -import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source'; - -import { SegmentedSearchRequestProvider } from '../segmented_search_request'; - -describe('SegmentedSearchRequest index selection', function () { - let Promise; - let SegmentedSearchRequest; - let MockSource; - let HitSortFn; - - NoDigestPromises.activateForSuite(); - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject((Private, $injector) => { - Promise = $injector.get('Promise'); - HitSortFn = Private(HitSortFnProv); - SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); - - MockSource = class { - constructor() { - return $injector.invoke(StubbedSearchSourceProvider); - } - }; - })); - - it('queries with size until all 500 docs returned', async function () { - const searchSource = new MockSource(); - const indexPattern = searchSource.getField('index'); - sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve([ - { index: 'one', min: 0, max: 1 }, - { index: 'two', min: 0, max: 1 }, - { index: 'three', min: 0, max: 1 }, - { index: 'four', min: 0, max: 1 }, - { index: 'five', min: 0, max: 1 }, - ])); - - const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} }); - req._handle.setDirection('desc'); - req._handle.setSortFn(new HitSortFn('desc')); - req._handle.setSize(500); - await req.start(); - - // first 200 - expect((await req.getFetchParams()).body.size).to.be(500); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - - // total = 400 - expect((await req.getFetchParams()).body.size).to.be(500); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - - // total = 600 - expect((await req.getFetchParams()).body.size).to.be(500); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - - expect((await req.getFetchParams()).body.size).to.be(0); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - - expect((await req.getFetchParams()).body.size).to.be(0); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - }); - - it(`sets size 0 for indices that couldn't preclude hits`, async function () { - const searchSource = new MockSource(); - const indexPattern = searchSource.getField('index'); - - // the segreq is looking for 10 documents, and we will give it ten docs with time:5 in the first response. - // on the second index it should still request 10 documents because it could produce documents with time:5. - // the next two indexes will get size 0, since they couldn't produce documents with the time:5 - // the final index will get size:10, because it too can produce docs with time:5 - sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve([ - { index: 'one', min: 0, max: 10 }, - { index: 'two', min: 0, max: 10 }, - { index: 'three', min: 12, max: 20 }, - { index: 'four', min: 15, max: 20 }, - { index: 'five', min: 5, max: 50 }, - ])); - - const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} }); - req._handle.setDirection('desc'); - req._handle.setSortFn(new HitSortFn('desc')); - req._handle.setSize(10); - await req.start(); - - // first 10 - expect((await req.getFetchParams()).body.size).to.be(10); - await req.handleResponse({ - hits: { total: 1000, hits: times(10, () => ({ _source: { time: 5 } })) } - }); - - // total = 400 - expect((await req.getFetchParams()).body.size).to.be(10); - await req.handleResponse({ - hits: { total: 1000, hits: times(10, () => ({ _source: { time: 5 } })) } - }); - - // total = 600 - expect((await req.getFetchParams()).body.size).to.be(0); - await req.handleResponse({ - hits: { total: 1000, hits: [] } - }); - - expect((await req.getFetchParams()).body.size).to.be(0); - await req.handleResponse({ - hits: { total: 1000, hits: [] } - }); - - expect((await req.getFetchParams()).body.size).to.be(10); - await req.handleResponse({ - hits: { total: 1000, hits: times(10, () => ({ _source: { time: 5 } })) } - }); - }); -}); diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js deleted file mode 100644 index 33b8140b746f5..0000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js +++ /dev/null @@ -1,88 +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 sinon from 'sinon'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; - -import { SegmentedSearchRequestProvider } from '../segmented_search_request'; -import { SearchRequestProvider } from '../../search_request'; - -describe('SegmentedSearchRequest', () => { - let Promise; - let SegmentedSearchRequest; - let segmentedReq; - let abstractReqStart; - - beforeEach(ngMock.module('kibana')); - - beforeEach(ngMock.inject((Private, $injector) => { - Promise = $injector.get('Promise'); - SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); - - const SearchRequest = Private(SearchRequestProvider); - abstractReqStart = sinon.stub(SearchRequest.prototype, 'start').callsFake(() => { - const promise = Promise.resolve(); - sinon.spy(promise, 'then'); - return promise; - }); - })); - - describe('#start()', () => { - let returned; - beforeEach(() => { - init(); - returned = segmentedReq.start(); - }); - - it('returns promise', () => { - expect(returned.then).to.be.Function; - }); - - it('calls AbstractReq#start()', () => { - sinon.assert.calledOnce(abstractReqStart); - }); - - it('listens to promise from super.start()', () => { - sinon.assert.calledOnce(abstractReqStart); - const promise = abstractReqStart.firstCall.returnValue; - sinon.assert.calledOnce(promise.then); - }); - }); - - function init() { - segmentedReq = new SegmentedSearchRequest({ source: mockSource(), errorHandler: () => {} }); - } - - function mockSource() { - return { - get: sinon.stub().returns(mockIndexPattern()), - }; - } - - function mockIndexPattern() { - return { - toDetailedIndexList: sinon.stub().returns(Promise.resolve([ - { index: 1, min: 0, max: 1 }, - { index: 2, min: 0, max: 1 }, - { index: 3, min: 0, max: 1 }, - ])) - }; - } -}); diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js deleted file mode 100644 index 7b499fbd87e0e..0000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js +++ /dev/null @@ -1,70 +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 ngMock from 'ng_mock'; -import expect from '@kbn/expect'; - -import HitSortFnProv from 'plugins/kibana/discover/_hit_sort_fn'; -import NoDigestPromises from 'test_utils/no_digest_promises'; -import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source'; - -import { SegmentedSearchRequestProvider } from '../segmented_search_request'; - -describe('SegmentedSearchRequest size picking', function () { - let SegmentedSearchRequest; - let MockSource; - let HitSortFn; - - NoDigestPromises.activateForSuite(); - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject((Private, $injector) => { - HitSortFn = Private(HitSortFnProv); - SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); - - MockSource = class { - constructor() { - return $injector.invoke(StubbedSearchSourceProvider); - } - }; - })); - - describe('without a size', function () { - it('does not set the request size', async function () { - const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} }); - req._handle.setDirection('desc'); - req._handle.setSortFn(new HitSortFn('desc')); - await req.start(); - - expect((await req.getFetchParams()).body).to.not.have.property('size'); - }); - }); - - describe('with a size', function () { - it('sets the request size to the entire desired size', async function () { - const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} }); - req._handle.setDirection('desc'); - req._handle.setSize(555); - req._handle.setSortFn(new HitSortFn('desc')); - await req.start(); - - expect((await req.getFetchParams()).body).to.have.property('size', 555); - }); - }); -}); diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/index.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/index.js deleted file mode 100644 index b10169bd42eeb..0000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/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 { SegmentedSearchRequestProvider } from './segmented_search_request'; diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js deleted file mode 100644 index b7a638b4ed159..0000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js +++ /dev/null @@ -1,59 +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 { EventsProvider } from '../../../../events'; - -export function SegmentedHandleProvider(Private) { - const Events = Private(EventsProvider); - - const segmentedRequest = Symbol('Actual Segmented Request'); - - /** - * Simple class for creating an object to send to the - * requester of a SegmentedSearchRequest. Since the SegmentedSearchRequest - * extends AbstractRequest, it wasn't able to be the event - * emitter it was born to be. This provides a channel for - * setting values on the segmented request, and an event - * emitter for the request to speak outwardly - * - * @param {SegmentedSearchRequest} - req - the request this handle relates to - */ - return class SegmentedHandle extends Events { - constructor(req) { - super(); - this[segmentedRequest] = req; - } - - setDirection(...args) { - this[segmentedRequest].setDirection(...args); - } - - setSize(...args) { - this[segmentedRequest].setSize(...args); - } - - setMaxSegments(...args) { - this[segmentedRequest].setMaxSegments(...args); - } - - setSortFn(...args) { - this[segmentedRequest].setSortFn(...args); - } - }; -} diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js deleted file mode 100644 index 6ab49eee4fe65..0000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js +++ /dev/null @@ -1,346 +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 _ from 'lodash'; -import { timefilter } from 'ui/timefilter'; -import { SearchRequestProvider } from '../search_request'; -import { SegmentedHandleProvider } from './segmented_handle'; -import { pushAll } from '../../../../utils/collection'; - -export function SegmentedSearchRequestProvider(Private, config) { - const SearchRequest = Private(SearchRequestProvider); - const SegmentedHandle = Private(SegmentedHandleProvider); - - class SegmentedSearchRequest extends SearchRequest { - constructor({ source, defer, errorHandler, initFn }) { - super({ source, defer, errorHandler }); - - this.type = 'segmented'; - - // segmented request specific state - this._initFn = initFn; - - this._desiredSize = null; - this._maxSegments = config.get('courier:maxSegmentCount'); - this._direction = 'desc'; - this._sortFn = null; - this._queueCreated = false; - this._handle = new SegmentedHandle(this); - - this._hitWindow = null; - - // prevent the source from changing between requests, - // all calls will return the same promise - this._getFlattenedSource = _.once(this._getFlattenedSource); - } - - /********* - ** SearchReq overrides - *********/ - - start() { - return super.start().then(() => { - this._complete = []; - this._active = null; - this._segments = []; - this._all = []; - this._queue = []; - - this._mergedResp = { - took: 0, - hits: { - hits: [], - total: 0, - max_score: 0 - } - }; - - // give the request consumer a chance to receive each segment and set - // parameters via the handle - if (_.isFunction(this._initFn)) this._initFn(this._handle); - return this._createQueue(); - }) - .then((queue) => { - if (this.stopped) return; - - this._all = queue.slice(0); - - // Send the initial fetch status - return this._reportStatus(); - }); - } - - continue() { - return this._reportStatus(); - } - - getFetchParams() { - return this._getFlattenedSource().then(flatSource => { - const params = _.cloneDeep(flatSource); - - // calculate the number of indices to fetch in this request in order to prevent - // more than this._maxSegments requests. We use Math.max(1, n) to ensure that each request - // has at least one index pattern, and Math.floor() to make sure that if the - // number of indices does not round out evenly the extra index is tacked onto the last - // request, making sure the first request returns faster. - const remainingSegments = this._maxSegments - this._segments.length; - const indexCount = Math.max(1, Math.floor(this._queue.length / remainingSegments)); - - const indices = this._active = this._queue.splice(0, indexCount); - params.index = indices.map(({ index }) => index).join(','); - - if (_.isNumber(this._desiredSize)) { - params.body.size = this._pickSizeForIndices(indices); - } - - return params; - }); - } - - handleResponse(resp) { - return this._consumeSegment(resp); - } - - filterError(resp) { - if (/ClusterBlockException.*index\sclosed/.test(resp.error)) { - this._consumeSegment(false); - return true; - } - } - - isIncomplete() { - const queueNotCreated = !this._queueCreated; - const queueNotEmpty = this._queue.length > 0; - return queueNotCreated || queueNotEmpty; - } - - clone() { - return new SegmentedSearchRequest(this.source, this.defer, this._initFn); - } - - complete() { - this._reportStatus(); - this._handle.emit('complete'); - return super.complete(); - } - - /********* - ** SegmentedSearchRequest specific methods - *********/ - - - /** - * Set the sort total number of segments to emit - * - * @param {number} - */ - setMaxSegments(maxSegments) { - this._maxSegments = Math.max(_.parseInt(maxSegments), 1); - } - - /** - * Set the sort direction for the request. - * - * @param {string} dir - one of 'asc' or 'desc' - */ - setDirection(dir) { - switch (dir) { - case 'asc': - case 'desc': - return (this._direction = dir); - default: - throw new TypeError('unknown sort direction "' + dir + '"'); - } - } - - /** - * Set the function that will be used to sort the rows - * - * @param {fn} - */ - setSortFn(sortFn) { - this._sortFn = sortFn; - } - - /** - * Set the sort total number of documents to - * emit - * - * Setting to false will not limit the documents, - * if a number is set the size of the request to es - * will be updated on each new request - * - * @param {number|false} - */ - setSize(totalSize) { - this._desiredSize = _.parseInt(totalSize); - if (isNaN(this._desiredSize)) this._desiredSize = null; - } - - _createQueue() { - const timeBounds = timefilter.getBounds(); - const indexPattern = this.source.getField('index'); - this._queueCreated = false; - - return indexPattern.toDetailedIndexList(timeBounds.min, timeBounds.max, this._direction) - .then(queue => { - this._queue = queue; - this._queueCreated = true; - return queue; - }); - } - - _reportStatus() { - return this._handle.emit('status', { - total: this._queueCreated ? this._all.length : NaN, - complete: this._queueCreated ? this._complete.length : NaN, - remaining: this._queueCreated ? this._queue.length : NaN, - hitCount: this._queueCreated ? this._mergedResp.hits.hits.length : NaN - }); - } - - _getFlattenedSource() { - return this.source._flatten(); - } - - _consumeSegment(seg) { - const index = this._active; - this._complete.push(index); - if (!seg) return; // segment was ignored/filtered, don't store it - - const hadHits = _.get(this._mergedResp, 'hits.hits.length') > 0; - const gotHits = _.get(seg, 'hits.hits.length') > 0; - const firstHits = !hadHits && gotHits; - const haveHits = hadHits || gotHits; - - this._mergeSegment(seg); - this.resp = _.omit(this._mergedResp, '_bucketIndex'); - - if (firstHits) this._handle.emit('first', seg); - gotHits ? this._handle.emit('segment', seg) : this._handle.emit('emptySegment', seg); - if (haveHits) this._handle.emit('mergedSegment', this.resp); - } - - _mergeHits(hits) { - const mergedHits = this._mergedResp.hits.hits; - const desiredSize = this._desiredSize; - const sortFn = this._sortFn; - - pushAll(hits, mergedHits); - - if (sortFn) { - mergedHits.sort(sortFn); - } - - if (_.isNumber(desiredSize)) { - this._mergedResp.hits.hits = mergedHits.slice(0, desiredSize); - } - } - - _mergeSegment(seg) { - const merged = this._mergedResp; - - this._segments.push(seg); - - merged.took += seg.took; - merged.hits.total += seg.hits.total; - merged.hits.max_score = Math.max(merged.hits.max_score, seg.hits.max_score); - - if (_.size(seg.hits.hits)) { - this._mergeHits(seg.hits.hits); - this._detectHitsWindow(merged.hits.hits); - } - - if (!seg.aggregations) return; - - Object.keys(seg.aggregations).forEach(function (aggKey) { - - if (!merged.aggregations) { - // start merging aggregations - merged.aggregations = {}; - merged._bucketIndex = {}; - } - - if (!merged.aggregations[aggKey]) { - merged.aggregations[aggKey] = { - buckets: [] - }; - } - - seg.aggregations[aggKey].buckets.forEach(function (bucket) { - let mbucket = merged._bucketIndex[bucket.key]; - if (mbucket) { - mbucket.doc_count += bucket.doc_count; - return; - } - - mbucket = merged._bucketIndex[bucket.key] = bucket; - merged.aggregations[aggKey].buckets.push(mbucket); - }); - }); - } - - _detectHitsWindow(hits) { - hits = hits || []; - const indexPattern = this.source.getField('index'); - const desiredSize = this._desiredSize; - - const size = _.size(hits); - if (!_.isNumber(desiredSize) || size < desiredSize) { - this._hitWindow = { - size: size, - min: -Infinity, - max: Infinity - }; - return; - } - - let min; - let max; - - hits.forEach(function (deepHit) { - const hit = indexPattern.flattenHit(deepHit); - const time = hit[indexPattern.timeFieldName]; - if (min == null || time < min) min = time; - if (max == null || time > max) max = time; - }); - - this._hitWindow = { size, min, max }; - } - - _pickSizeForIndices(indices) { - const hitWindow = this._hitWindow; - const desiredSize = this._desiredSize; - - if (!_.isNumber(desiredSize)) return null; - // we don't have any hits yet, get us more info! - if (!hitWindow) return desiredSize; - // the order of documents isn't important, just get us more - if (!this._sortFn) return Math.max(desiredSize - hitWindow.size, 0); - // if all of the documents in every index fall outside of our current doc set, we can ignore them. - const someOverlap = indices.some(function (index) { - return index.min <= hitWindow.max && hitWindow.min <= index.max; - }); - - return someOverlap ? desiredSize : 0; - } - } - - return SegmentedSearchRequest; -} diff --git a/src/legacy/ui/public/courier/search_source/search_source.js b/src/legacy/ui/public/courier/search_source/search_source.js index 8fc71bff40a84..7943973bf51ed 100644 --- a/src/legacy/ui/public/courier/search_source/search_source.js +++ b/src/legacy/ui/public/courier/search_source/search_source.js @@ -76,7 +76,6 @@ import { buildEsQuery, getEsQueryConfig, filterMatchesIndex } from '@kbn/es-quer import '../../promises'; import { NormalizeSortRequestProvider } from './_normalize_sort_request'; import { SearchRequestProvider } from '../fetch/request'; -import { SegmentedSearchRequestProvider } from '../fetch/request/segmented_search_request'; import { searchRequestQueue } from '../search_request_queue'; import { FetchSoonProvider } from '../fetch'; @@ -117,7 +116,6 @@ function isIndexPattern(val) { export function SearchSourceProvider(Promise, Private, config) { const SearchRequest = Private(SearchRequestProvider); - const SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); const normalizeSortRequest = Private(NormalizeSortRequestProvider); const fetchSoon = Private(FetchSoonProvider); const { fieldWildcardFilter } = Private(FieldWildcardProvider); @@ -390,26 +388,6 @@ export function SearchSourceProvider(Promise, Private, config) { }); } - onBeginSegmentedFetch(initFunction) { - const self = this; - return new Promise((resolve, reject) => { - function addRequest() { - const defer = Promise.defer(); - const errorHandler = (request, error) => { - reject(error); - request.abort(); - }; - const req = new SegmentedSearchRequest({ source: self, defer, errorHandler, initFn: initFunction }); - - // Return promises created by the completion handler so that - // errors will bubble properly - return req.getCompletePromise().then(addRequest); - } - - addRequest(); - }); - } - async getSearchRequestBody() { const searchRequest = await this._flatten(); return searchRequest.body; diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2e521829aaf8b..3312215623b4a 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -815,8 +815,6 @@ "kbn.advancedSettings.courier.ignoreFilterTitle": "忽略筛选", "kbn.advancedSettings.courier.maxRequestsText": "控制用于 Kibana 发送的 _msearch 请求的 “{maxRequestsLink}” 设置。设置为 0 可禁用此配置并使用 Elasticsearch 默认值。", "kbn.advancedSettings.courier.maxRequestsTitle": "最大并发分片请求数", - "kbn.advancedSettings.courier.maxSegmentCountText": "Discover 中的请求将拆分成段,以防止大型请求发送给 Elasticsearch。此设置会尝试阻止段列表过长,否则会导致系统花费很长时间处理请求。", - "kbn.advancedSettings.courier.maxSegmentCountTitle": "最大段计数", "kbn.advancedSettings.courier.requestPreferenceText": "允许您设置用于处理搜索请求的分片。
      \n
    • {sessionId}: 限制在相同分片上执行所有搜索请求的操作。\n 这有利于在各个请求之间复用分片缓存。
    • \n
    • {custom}: 允许您定义自己的首选项。\n 使用 courier:customRequestPreference 定制首选项值。
    • \n
    • {none}: 表示不设置首选项。\n 这可能会提供更佳的性能,因此请求可以在所有分片副本上进行分配。\n 不过,结果可能会不一致,因为不同的分片可能处于不同的刷新状态。
    • \n
    ", "kbn.advancedSettings.courier.requestPreferenceTitle": "请求首选项", "kbn.advancedSettings.csv.quoteValuesText": "在 csv 导出中是否应使用引号引起值?", @@ -1280,8 +1278,6 @@ "kbn.discover.hitsPluralTitle": "{hits, plural, one {次命中} other {次命中}}", "kbn.discover.howToChangeTheTimeTooltip": "要更改时间,请单击导航栏中的时钟图标", "kbn.discover.howToSeeOtherMatchingDocumentsDescription": "以下是匹配您的搜索的前 {sampleSize} 个文档,请优化您的搜索以查看其他文档。", - "kbn.discover.inspectorRequest.segmentFetchCompleteStatusDescription": "此请求将查询 Elasticsearch 以获取搜索的数据。", - "kbn.discover.inspectorRequest.segmentFetchCompleteStatusTitle": "段 {fetchCompleteStatus}", "kbn.discover.localMenu.inspectTitle": "检查", "kbn.discover.localMenu.localMenu.newSearchTitle": "新建", "kbn.discover.localMenu.newSearchDescription": "新搜索", @@ -8174,4 +8170,4 @@ "xpack.watcher.watchActionsTitle": "满足后将执行 {watchActionsCount, plural, one{# 个操作} other {# 个操作}}", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} \ No newline at end of file +} From 786423a85acb647157cf6d4bbdb28bb86fd38b28 Mon Sep 17 00:00:00 2001 From: "dave.snider@gmail.com" Date: Wed, 27 Mar 2019 16:21:40 -0700 Subject: [PATCH 69/96] EUI@9.7.0 (#34011) --- package.json | 2 +- .../plugins/kbn_tp_run_pipeline/package.json | 2 +- .../plugins/kbn_tp_custom_visualizations/package.json | 2 +- .../plugins/kbn_tp_sample_panel_action/package.json | 2 +- .../plugins/kbn_tp_visualize_embedding/package.json | 2 +- x-pack/package.json | 2 +- yarn.lock | 8 ++++---- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 0047641cc184b..3514f8777e3ce 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "@babel/polyfill": "^7.2.5", "@babel/register": "^7.0.0", "@elastic/datemath": "5.0.2", - "@elastic/eui": "9.6.0", + "@elastic/eui": "9.7.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.3.2", diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json index b97f284221483..3135a040cec92 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.6.0", + "@elastic/eui": "9.7.0", "react": "^16.8.0", "react-dom": "^16.8.0" } diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json index 116ee0f4ee7ce..cf922f28b944a 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.6.0", + "@elastic/eui": "9.7.0", "react": "^16.8.0" } } diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json index 78c26895530d1..c7148b8ce38f8 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.6.0", + "@elastic/eui": "9.7.0", "react": "^16.8.0" }, "scripts": { diff --git a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json b/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json index 96048fe01749b..e2a14cf36f71e 100644 --- a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json +++ b/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.6.0", + "@elastic/eui": "9.7.0", "react": "^16.8.0", "react-dom": "^16.8.0" } diff --git a/x-pack/package.json b/x-pack/package.json index bcd84b2c65b9c..f33a8da23137c 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -139,7 +139,7 @@ "@babel/register": "^7.0.0", "@babel/runtime": "^7.3.4", "@elastic/datemath": "5.0.2", - "@elastic/eui": "9.6.0", + "@elastic/eui": "9.7.0", "@elastic/node-crypto": "0.1.2", "@elastic/numeral": "2.3.2", "@kbn/babel-preset": "1.0.0", diff --git a/yarn.lock b/yarn.lock index d4498b28ce127..a09253ff177c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -834,10 +834,10 @@ tabbable "^1.1.0" uuid "^3.1.0" -"@elastic/eui@9.6.0": - version "9.6.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-9.6.0.tgz#740107869b1448348e603d4b1992daf3d5004d3a" - integrity sha512-/uZdPaf2TwTCT3MJsoz4yOqOVrAWhb3ziZtXIUIL/EWGQoha6Z8+wEhpixW472KVvp8bGJl3uDoTwTzDk3TAKw== +"@elastic/eui@9.7.0": + version "9.7.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-9.7.0.tgz#6da25d665936fba713d24bfec3beba8c20a4272b" + integrity sha512-2cXEvAxYEfS1i5ZwhSl63rGT6jMQOQHed4RLFnuf0xmZyUjIO9he8EVY9YAH2eFfrRvEVggQltLLEI+JXhiqSA== dependencies: "@types/lodash" "^4.14.116" "@types/numeral" "^0.0.25" From 7a4b3ced6051f0b2e6147d79d4a636fb583b56cf Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Wed, 27 Mar 2019 19:53:19 -0700 Subject: [PATCH 70/96] Update copy to refer to Cross-Cluster Search/Replication. (#33872) --- .../create_index_pattern_wizard/CREATE_INDEX_PATTERN.md | 2 +- .../__jest__/client_integration/home.test.js | 2 +- x-pack/plugins/cross_cluster_replication/public/app/app.js | 4 ++-- .../public/app/components/follower_index_unfollow_provider.js | 4 ++-- .../public/app/sections/home/home.js | 2 +- .../public/app/services/breadcrumbs.js | 2 +- x-pack/plugins/cross_cluster_replication/public/index.scss | 2 +- .../cross_cluster_replication/public/register_routes.js | 2 +- .../server/lib/check_license/check_license.js | 2 +- x-pack/plugins/monitoring/server/lib/ccs_utils.js | 2 +- .../apis/management/cross_cluster_replication/index.js | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/CREATE_INDEX_PATTERN.md b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/CREATE_INDEX_PATTERN.md index ab2cb1ac7905c..6e01bf001691e 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/CREATE_INDEX_PATTERN.md +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/CREATE_INDEX_PATTERN.md @@ -6,7 +6,7 @@ This is meant to serve as a guide to this area of code. In order to prevent future regressions, there are a few scenarios that need to be tested with each change to this area of the code. -- Cross cluster search +- Cross-cluster search - Ensure changes work properly in a CCS environment - A solid CCS environment involves various indices on all nodes including the controlling node. - Alias support diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js index e63a4653d1896..b8056e2625342 100644 --- a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js @@ -53,7 +53,7 @@ describe('', () => { test('should set the correct an app title', () => { expect(exists('ccrAppTitle')).toBe(true); - expect(find('ccrAppTitle').text()).toEqual('Cross Cluster Replication'); + expect(find('ccrAppTitle').text()).toEqual('Cross-Cluster Replication'); }); test('should have 2 tabs to switch between "Follower indices" & "Auto-follow patterns"', () => { diff --git a/x-pack/plugins/cross_cluster_replication/public/app/app.js b/x-pack/plugins/cross_cluster_replication/public/app/app.js index 781b5040b2b66..d07712727aa77 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/app.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/app.js @@ -95,7 +95,7 @@ export class App extends Component { // This error isn't an HTTP error, so let the fatal error screen tell the user something // unexpected happened. fatalError(error, i18n.translate('xpack.crossClusterReplication.app.checkPermissionsFatalErrorTitle', { - defaultMessage: 'Cross Cluster Replication app', + defaultMessage: 'Cross-Cluster Replication app', })); } } @@ -196,7 +196,7 @@ export class App extends Component {

    @@ -111,7 +111,7 @@ class FollowerIndexUnfollowProviderUi extends PureComponent {

    diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js index b9e7f68e77614..e206e954e51d8 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js @@ -73,7 +73,7 @@ export class CrossClusterReplicationHome extends PureComponent {

    diff --git a/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.js b/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.js index 318c9e211a128..f8c8cc710964a 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.js @@ -9,7 +9,7 @@ import { BASE_PATH } from '../../../common/constants'; export const listBreadcrumb = { text: i18n.translate('xpack.crossClusterReplication.homeBreadcrumbTitle', { - defaultMessage: 'Cross Cluster Replication', + defaultMessage: 'Cross-Cluster Replication', }), href: `#${BASE_PATH}`, }; diff --git a/x-pack/plugins/cross_cluster_replication/public/index.scss b/x-pack/plugins/cross_cluster_replication/public/index.scss index fc1b118a5f77f..6f65dc04d4427 100644 --- a/x-pack/plugins/cross_cluster_replication/public/index.scss +++ b/x-pack/plugins/cross_cluster_replication/public/index.scss @@ -1,7 +1,7 @@ // Import the EUI global scope so we can use EUI constants @import 'src/legacy/ui/public/styles/_styling_constants'; -// Cross Cluster Replication plugin styles +// Cross-Cluster Replication plugin styles // Prefix all styles with "ccr" to avoid conflicts. // Examples diff --git a/x-pack/plugins/cross_cluster_replication/public/register_routes.js b/x-pack/plugins/cross_cluster_replication/public/register_routes.js index 960ffe844fae6..f29bf4efaba8e 100644 --- a/x-pack/plugins/cross_cluster_replication/public/register_routes.js +++ b/x-pack/plugins/cross_cluster_replication/public/register_routes.js @@ -22,7 +22,7 @@ if (chrome.getInjected('ccrUiEnabled')) { esSection.register('ccr', { visible: true, - display: i18n.translate('xpack.crossClusterReplication.appTitle', { defaultMessage: 'Cross Cluster Replication' }), + display: i18n.translate('xpack.crossClusterReplication.appTitle', { defaultMessage: 'Cross-Cluster Replication' }), order: 4, url: `#${BASE_PATH}` }); diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/check_license/check_license.js b/x-pack/plugins/cross_cluster_replication/server/lib/check_license/check_license.js index fb99de8ab5d97..ddde694bc549a 100644 --- a/x-pack/plugins/cross_cluster_replication/server/lib/check_license/check_license.js +++ b/x-pack/plugins/cross_cluster_replication/server/lib/check_license/check_license.js @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; export function checkLicense(xpackLicenseInfo) { - const pluginName = 'Cross Cluster Replication'; + const pluginName = 'Cross-Cluster Replication'; // If, for some reason, we cannot get the license information // from Elasticsearch, assume worst case and disable diff --git a/x-pack/plugins/monitoring/server/lib/ccs_utils.js b/x-pack/plugins/monitoring/server/lib/ccs_utils.js index 30409960edd9e..5b3980d9619a8 100644 --- a/x-pack/plugins/monitoring/server/lib/ccs_utils.js +++ b/x-pack/plugins/monitoring/server/lib/ccs_utils.js @@ -7,7 +7,7 @@ /** * Prefix all comma separated index patterns within the original {@code indexPattern}. * - * Cross Cluster Search (CCS) prefixing is ignored if the user has disabled CCS via kibana.yml, + * Cross-cluster search (CCS) prefixing is ignored if the user has disabled CCS via kibana.yml, * which means that the index pattern will be returned without using {@code ccs}. * * @param {Object} config The Kibana configuration object. diff --git a/x-pack/test/api_integration/apis/management/cross_cluster_replication/index.js b/x-pack/test/api_integration/apis/management/cross_cluster_replication/index.js index a033a03d613f9..e1cc6d7cf2c14 100644 --- a/x-pack/test/api_integration/apis/management/cross_cluster_replication/index.js +++ b/x-pack/test/api_integration/apis/management/cross_cluster_replication/index.js @@ -5,7 +5,7 @@ */ export default function ({ loadTestFile }) { - describe('cross cluster replication', () => { + describe('cross-cluster replication', () => { loadTestFile(require.resolve('./auto_follow_pattern')); loadTestFile(require.resolve('./follower_indices')); }); From 424edafdfda84c8c9dbf55b61d2d78e2b1b2d8bc Mon Sep 17 00:00:00 2001 From: Philipp B Date: Thu, 28 Mar 2019 09:58:20 +0300 Subject: [PATCH 71/96] (Accessibility) Viz type selection button should read more clearly in screenreader #29475 (#33434) * popover announces itself, button gives predictable behavior; menutitems * drops incorrect button aria label * replace aria-describedby with translated label --- .../__snapshots__/new_vis_modal.test.tsx.snap | 40 +++++++++++++++++++ .../public/visualize/wizard/new_vis_modal.tsx | 16 +++++++- .../wizard/type_selection/type_selection.tsx | 1 + 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap index aa33eb4ab1d02..b638849ae0d62 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap @@ -162,7 +162,9 @@ exports[`NewVisModal filter for visualization types should render as expected 1` data-focus-lock-disabled="false" >
    + +
    + + , +] +`; + +exports[`Service Overview -> View should render services, when list is not empty 1`] = ` +NodeList [ + + +
    + Name +
    + + + +
    + Agent +
    +
    + go +
    + + +
    + Avg. response time +
    +
    + 1 ms +
    + + +
    + Trans. per minute +
    +
    + 400.0 tpm +
    + + +
    + Errors per minute +
    +
    + 500.0 err. +
    + + , + + +
    + Name +
    + + + +
    + Agent +
    +
    + python +
    + + +
    + Avg. response time +
    +
    + 0 ms +
    + + +
    + Trans. per minute +
    +
    + 100.0 tpm +
    + + +
    + Errors per minute +
    +
    + 200.0 err. +
    + + , +] +`; diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/index.ts b/x-pack/plugins/apm/public/components/app/ServiceOverview/index.ts index 7e2ec20677c3d..378bf3118886a 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/index.ts +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/index.ts @@ -5,14 +5,12 @@ */ import { connect } from 'react-redux'; -import { getServiceList } from 'x-pack/plugins/apm/public/store/reactReduxRequest/serviceList'; import { IReduxState } from 'x-pack/plugins/apm/public/store/rootReducer'; import { getUrlParams } from 'x-pack/plugins/apm/public/store/urlParams'; import { ServiceOverview as View } from './view'; function mapStateToProps(state = {} as IReduxState) { return { - serviceList: getServiceList(state), urlParams: getUrlParams(state) }; } diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/view.tsx b/x-pack/plugins/apm/public/components/app/ServiceOverview/view.tsx index 1c11b5deff8b4..3480aae74d5c1 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/view.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/view.tsx @@ -5,59 +5,32 @@ */ import { EuiPanel } from '@elastic/eui'; -import React, { Component } from 'react'; -import { RRRRenderResponse } from 'react-redux-request'; +import React from 'react'; import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams'; -import { IServiceListItem } from 'x-pack/plugins/apm/server/lib/services/get_services'; +import { useFetcher } from '../../../hooks/useFetcher'; +import { loadServiceList } from '../../../services/rest/apm/services'; import { loadAgentStatus } from '../../../services/rest/apm/status_check'; -import { ServiceListRequest } from '../../../store/reactReduxRequest/serviceList'; import { NoServicesMessage } from './NoServicesMessage'; import { ServiceList } from './ServiceList'; interface Props { urlParams: IUrlParams; - serviceList: RRRRenderResponse; } -interface State { - // any data submitted from APM agents found (not just in the given time range) - historicalDataFound: boolean; -} - -export class ServiceOverview extends Component { - public state = { historicalDataFound: true }; - - public async checkForHistoricalData() { - const result = await loadAgentStatus(); - this.setState({ historicalDataFound: result.dataFound }); - } - - public componentDidMount() { - this.checkForHistoricalData(); - } - - public render() { - const { urlParams } = this.props; - - // Render method here uses this.props.serviceList instead of received "data" from RRR - // to make it easier to test -- mapStateToProps uses the RRR selector so the data - // is the same either way - return ( - - ( - - } - /> - )} - /> - - ); - } +export function ServiceOverview({ urlParams }: Props) { + const { start, end, kuery } = urlParams; + const { data: agentStatus = true } = useFetcher(() => loadAgentStatus(), []); + const { data: serviceListData } = useFetcher( + () => loadServiceList({ start, end, kuery }), + [start, end, kuery] + ); + + return ( + + } + /> + + ); } diff --git a/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx b/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx index 06d548ea8661d..b7ac9f63f61cc 100644 --- a/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx +++ b/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx @@ -11,6 +11,7 @@ import styled from 'styled-components'; import { ITransactionGroup } from 'x-pack/plugins/apm/server/lib/transaction_groups/transform'; import { fontSizes, truncate } from '../../../style/variables'; import { asMillis } from '../../../utils/formatters'; +import { EmptyMessage } from '../../shared/EmptyMessage'; import { ImpactBar } from '../../shared/ImpactBar'; import { TransactionLink } from '../../shared/Links/TransactionLink'; import { ITableColumn, ManagedTable } from '../../shared/ManagedTable'; @@ -22,7 +23,6 @@ const StyledTransactionLink = styled(TransactionLink)` interface Props { items: ITransactionGroup[]; - noItemsMessage: React.ReactNode; isLoading: boolean; } @@ -88,7 +88,15 @@ const traceListColumns: Array> = [ } ]; -export function TraceList({ items = [], noItemsMessage, isLoading }: Props) { +const noItemsMessage = ( + +); + +export function TraceList({ items = [], isLoading }: Props) { const noItems = isLoading ? null : noItemsMessage; return ( loadTraceList({ start, end, kuery }), + [start, end, kuery] + ); return ( - ) => ( - - } - /> - )} - /> + ); } diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx index 5a5e4977458b8..353332e76e4fe 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx @@ -52,7 +52,7 @@ export function getFormattedBuckets(buckets: IBucket[], bucketSize: number) { interface Props { location: Location; - distribution: ITransactionDistributionAPIResponse; + distribution?: ITransactionDistributionAPIResponse; urlParams: IUrlParams; } @@ -95,9 +95,45 @@ export class TransactionDistribution extends Component { ); }; + public redirectToTransactionType() { + const { urlParams, location, distribution } = this.props; + + if ( + !distribution || + !distribution.defaultSample || + urlParams.traceId || + urlParams.transactionId + ) { + return; + } + + const { traceId, transactionId } = distribution.defaultSample; + + history.replace({ + ...location, + search: fromQuery({ + ...toQuery(location.search), + traceId, + transactionId + }) + }); + } + + public componentDidMount() { + this.redirectToTransactionType(); + } + + public componentDidUpdate() { + this.redirectToTransactionType(); + } + public render() { const { location, distribution, urlParams } = this.props; + if (!distribution || !urlParams.traceId || !urlParams.transactionId) { + return null; + } + const buckets = getFormattedBuckets( distribution.buckets, distribution.bucketSize @@ -163,7 +199,7 @@ export class TransactionDistribution extends Component { bucketIndex={bucketIndex} onClick={(bucket: IChartPoint) => { if (bucket.sample && bucket.y > 0) { - history.replace({ + history.push({ ...location, search: fromQuery({ ...toQuery(location.search), diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts index e8196261a2a73..067bfd628764b 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts @@ -96,13 +96,12 @@ describe('waterfall_helpers', () => { it('should return full waterfall', () => { const entryTransactionId = 'myTransactionId1'; - const errorCountsByTransactionId = { + const errorsPerTransaction = { myTransactionId1: 2, myTransactionId2: 3 }; const waterfall = getWaterfall( - hits, - errorCountsByTransactionId, + { trace: hits, errorsPerTransaction }, entryTransactionId ); expect(waterfall.orderedItems.length).toBe(6); @@ -112,13 +111,12 @@ describe('waterfall_helpers', () => { it('should return partial waterfall', () => { const entryTransactionId = 'myTransactionId2'; - const errorCountsByTransactionId = { + const errorsPerTransaction = { myTransactionId1: 2, myTransactionId2: 3 }; const waterfall = getWaterfall( - hits, - errorCountsByTransactionId, + { trace: hits, errorsPerTransaction }, entryTransactionId ); expect(waterfall.orderedItems.length).toBe(4); @@ -128,13 +126,12 @@ describe('waterfall_helpers', () => { it('getTransactionById', () => { const entryTransactionId = 'myTransactionId1'; - const errorCountsByTransactionId = { + const errorsPerTransaction = { myTransactionId1: 2, myTransactionId2: 3 }; const waterfall = getWaterfall( - hits, - errorCountsByTransactionId, + { trace: hits, errorsPerTransaction }, entryTransactionId ); const transaction = waterfall.getTransactionById('myTransactionId2'); diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts index 6056551d41df1..5e54300427f88 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts @@ -239,8 +239,7 @@ function createGetTransactionById(itemsById: IWaterfallIndex) { } export function getWaterfall( - trace: TraceAPIResponse['trace'], - errorsPerTransaction: TraceAPIResponse['errorsPerTransaction'], + { trace, errorsPerTransaction }: TraceAPIResponse, entryTransactionId?: Transaction['transaction']['id'] ): IWaterfall { if (isEmpty(trace) || !entryTransactionId) { diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/view.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/view.tsx index 7b9eff0cccf3f..aa5f0ef31224b 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/view.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/view.tsx @@ -7,10 +7,11 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Location } from 'history'; +import _ from 'lodash'; import React from 'react'; -import { TransactionDetailsChartsRequest } from '../../../store/reactReduxRequest/transactionDetailsCharts'; -import { TransactionDistributionRequest } from '../../../store/reactReduxRequest/transactionDistribution'; -import { WaterfallRequest } from '../../../store/reactReduxRequest/waterfall'; +import { useTransactionDetailsCharts } from '../../../hooks/useTransactionDetailsCharts'; +import { useTransactionDistribution } from '../../../hooks/useTransactionDistribution'; +import { useWaterfall } from '../../../hooks/useWaterfall'; import { IUrlParams } from '../../../store/urlParams'; import { TransactionCharts } from '../../shared/charts/TransactionCharts'; import { EmptyMessage } from '../../shared/EmptyMessage'; @@ -19,12 +20,18 @@ import { TransactionDistribution } from './Distribution'; import { Transaction } from './Transaction'; interface Props { - mlAvailable: boolean; urlParams: IUrlParams; location: Location; } export function TransactionDetailsView({ urlParams, location }: Props) { + const { data: distributionData } = useTransactionDistribution(urlParams); + const { data: transactionDetailsChartsData } = useTransactionDetailsCharts( + urlParams + ); + const { data: waterfall } = useWaterfall(urlParams); + const transaction = waterfall.getTransactionById(urlParams.transactionId); + return (
    @@ -32,75 +39,51 @@ export function TransactionDetailsView({ urlParams, location }: Props) { - - - ( - - )} + location={location} /> - ( - - )} + location={location} /> - { - const transaction = waterfall.getTransactionById( - urlParams.transactionId - ); - if (!transaction) { - return ( - - ); - } - return ( - - ); - }} - /> + {!transaction ? ( + + ) : ( + + )}
    ); } diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.js b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.js deleted file mode 100644 index b68d06d162a59..0000000000000 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.js +++ /dev/null @@ -1,74 +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 React from 'react'; -import { shallow } from 'enzyme'; -import { TransactionOverviewView } from '..'; - -jest.mock( - 'ui/chrome', - () => ({ - getBasePath: () => `/some/base/path`, - getInjected: key => { - if (key === 'mlEnabled') { - return true; - } - throw new Error(`inexpected key ${key}`); - }, - getUiSettingsClient: () => { - return { - get: key => { - switch (key) { - case 'timepicker:timeDefaults': - return { from: 'now-15m', to: 'now', mode: 'quick' }; - case 'timepicker:refreshIntervalDefaults': - return { display: 'Off', pause: false, value: 0 }; - default: - throw new Error(`Unexpected config key: ${key}`); - } - } - }; - } - }), - { virtual: true } -); - -const setup = () => { - const props = { - agentName: 'test-agent', - serviceName: 'test-service', - serviceTransactionTypes: ['a', 'b'], - location: {}, - history: { - push: jest.fn() - }, - urlParams: { transactionType: 'test-type', serviceName: 'MyServiceName' } - }; - - const wrapper = shallow(); - return { props, wrapper }; -}; - -describe('TransactionOverviewView', () => { - it('should render null if there is no transaction type in the search string', () => { - const { wrapper } = setup(); - wrapper.setProps({ urlParams: { serviceName: 'MyServiceName' } }); - expect(wrapper).toMatchInlineSnapshot(`""`); - }); - - it('should render with type filter controls', () => { - const { wrapper } = setup(); - expect(wrapper).toMatchSnapshot(); - }); - - it('should render without type filter controls if there is just a single type', () => { - const { wrapper } = setup(); - wrapper.setProps({ - serviceTransactionTypes: ['a'] - }); - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx new file mode 100644 index 0000000000000..5c702658dbce3 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx @@ -0,0 +1,94 @@ +/* + * 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 createHistory from 'history/createHashHistory'; +import React from 'react'; +import { Provider } from 'react-redux'; +import { Router } from 'react-router-dom'; +import { queryByLabelText, render } from 'react-testing-library'; +// @ts-ignore +import configureStore from 'x-pack/plugins/apm/public/store/config/configureStore'; +import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams'; +import { TransactionOverview } from '..'; + +function setup(props: { + urlParams: IUrlParams; + serviceTransactionTypes: string[]; +}) { + const store = configureStore(); + const history = createHistory(); + history.replace = jest.fn(); + + const { container } = render( + + + + + + ); + + return { container, history }; +} + +describe('TransactionOverviewView', () => { + describe('when no transaction type is given', () => { + it('should render null', () => { + const { container } = setup({ + serviceTransactionTypes: ['firstType', 'secondType'], + urlParams: { + serviceName: 'MyServiceName' + } + }); + expect(container).toMatchInlineSnapshot(`
    `); + }); + + it('should redirect to first type', () => { + const { history } = setup({ + serviceTransactionTypes: ['firstType', 'secondType'], + urlParams: { + serviceName: 'MyServiceName' + } + }); + expect(history.replace).toHaveBeenCalledWith( + expect.objectContaining({ + pathname: '/MyServiceName/transactions/firstType' + }) + ); + }); + }); + + const FILTER_BY_TYPE_LABEL = 'Filter by type'; + + describe('when transactionType is selected and multiple transaction types are given', () => { + it('should render dropdown with transaction types', () => { + const { container } = setup({ + serviceTransactionTypes: ['firstType', 'secondType'], + urlParams: { + transactionType: 'secondType', + serviceName: 'MyServiceName' + } + }); + + expect( + queryByLabelText(container, FILTER_BY_TYPE_LABEL) + ).toMatchSnapshot(); + }); + }); + + describe('when a transaction type is selected, and there are no other transaction types', () => { + it('should not render a dropdown with transaction types', () => { + const { container } = setup({ + serviceTransactionTypes: ['firstType'], + urlParams: { + transactionType: 'firstType', + serviceName: 'MyServiceName' + } + }); + + expect(queryByLabelText(container, FILTER_BY_TYPE_LABEL)).toBeNull(); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap deleted file mode 100644 index d6a37bfaa2078..0000000000000 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap +++ /dev/null @@ -1,115 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`TransactionOverviewView should render with type filter controls 1`] = ` - - - - - - - - -

    - Transactions -

    -
    - - -
    -
    -`; - -exports[`TransactionOverviewView should render without type filter controls if there is just a single type 1`] = ` - - - - - -

    - Transactions -

    -
    - - -
    -
    -`; diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.tsx.snap b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.tsx.snap new file mode 100644 index 0000000000000..41374c9f8fff8 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TransactionOverviewView when transactionType is selected and multiple transaction types are given should render dropdown with transaction types 1`] = ` + +`; diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx index eb462a9f917c6..1aa497fb6e9d3 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx @@ -12,91 +12,120 @@ import { EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { Location } from 'history'; +import { first } from 'lodash'; import React from 'react'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import { TransactionCharts } from 'x-pack/plugins/apm/public/components/shared/charts/TransactionCharts'; import { legacyEncodeURIComponent } from 'x-pack/plugins/apm/public/components/shared/Links/url_helpers'; -import { TransactionListRequest } from 'x-pack/plugins/apm/public/store/reactReduxRequest/transactionList'; -import { TransactionOverviewChartsRequest } from 'x-pack/plugins/apm/public/store/reactReduxRequest/transactionOverviewCharts'; import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams'; +import { useTransactionList } from '../../../hooks/useTransactionList'; +import { useTransactionOverviewCharts } from '../../../hooks/useTransactionOverviewCharts'; import { TransactionList } from './List'; +import { useRedirect } from './useRedirect'; interface TransactionOverviewProps extends RouteComponentProps { urlParams: IUrlParams; serviceTransactionTypes: string[]; } -export class TransactionOverviewView extends React.Component< - TransactionOverviewProps -> { - public handleTypeChange = (event: React.ChangeEvent) => { - const { urlParams, history, location } = this.props; - const type = legacyEncodeURIComponent(event.target.value); - history.push({ +function getRedirectLocation({ + urlParams, + location, + serviceTransactionTypes +}: { + location: Location; + urlParams: IUrlParams; + serviceTransactionTypes: string[]; +}) { + const { serviceName, transactionType } = urlParams; + const firstTransactionType = first(serviceTransactionTypes); + if (!transactionType && firstTransactionType) { + return { ...location, - pathname: `/${urlParams.serviceName}/transactions/${type}` - }); - }; + pathname: `/${serviceName}/transactions/${firstTransactionType}` + }; + } +} - public render() { - const { urlParams, serviceTransactionTypes, location } = this.props; - const { serviceName, transactionType } = urlParams; +export function TransactionOverviewView({ + urlParams, + serviceTransactionTypes, + location, + history +}: TransactionOverviewProps) { + const { serviceName, transactionType } = urlParams; - // filtering by type is currently required - if (!serviceName || !transactionType) { - return null; - } + // redirect to first transaction type + useRedirect( + history, + getRedirectLocation({ + urlParams, + location, + serviceTransactionTypes + }) + ); - return ( - - {serviceTransactionTypes.length > 1 ? ( - - ({ - text: `${type}`, - value: type - }))} - value={transactionType} - onChange={this.handleTypeChange} - /> - - ) : null} + const { data: transactionOverviewCharts } = useTransactionOverviewCharts( + urlParams + ); - ( - - )} - /> + const { data: transactionListData } = useTransactionList(urlParams); - + // filtering by type is currently required + if (!serviceName || !transactionType) { + return null; + } - - -

    Transactions

    -
    - - ( - - )} + return ( + + {serviceTransactionTypes.length > 1 ? ( + + ({ + text: `${type}`, + value: type + }))} + value={transactionType} + onChange={event => { + const type = legacyEncodeURIComponent(event.target.value); + history.push({ + ...location, + pathname: `/${urlParams.serviceName}/transactions/${type}` + }); + }} /> -
    -
    - ); - } + + ) : null} + + + + + + + +

    Transactions

    +
    + + +
    + + ); } export const TransactionOverview = withRouter(TransactionOverviewView); diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/useRedirect.ts b/x-pack/plugins/apm/public/components/app/TransactionOverview/useRedirect.ts new file mode 100644 index 0000000000000..653ea73c1fed8 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/useRedirect.ts @@ -0,0 +1,16 @@ +/* + * 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 { History, Location } from 'history'; +import { useEffect } from 'react'; + +export function useRedirect(history: History, redirectLocation?: Location) { + useEffect(() => { + if (redirectLocation) { + history.replace(redirectLocation); + } + }); +} diff --git a/x-pack/plugins/apm/public/components/shared/FilterBar/__test__/DatePicker.test.tsx b/x-pack/plugins/apm/public/components/shared/FilterBar/__test__/DatePicker.test.tsx index 2ff953e1fe536..5508bc0b0148a 100644 --- a/x-pack/plugins/apm/public/components/shared/FilterBar/__test__/DatePicker.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/FilterBar/__test__/DatePicker.test.tsx @@ -11,7 +11,7 @@ import { MemoryRouter } from 'react-router-dom'; import { Store } from 'redux'; // @ts-ignore import configureStore from 'x-pack/plugins/apm/public/store/config/configureStore'; -import { mockNow } from 'x-pack/plugins/apm/public/utils/testHelpers'; +import { mockNow, tick } from 'x-pack/plugins/apm/public/utils/testHelpers'; import { DatePicker, DatePickerComponent } from '../DatePicker'; function mountPicker(initialState = {}) { @@ -54,8 +54,6 @@ describe('DatePicker', () => { }); }); - const tick = () => new Promise(resolve => setImmediate(resolve, 0)); - describe('refresh cycle', () => { let nowSpy: jest.Mock; beforeEach(() => { diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx index d62122b9137de..74ad7fb66c442 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx @@ -4,17 +4,220 @@ * you may not use this file except in compliance with the Elastic License. */ -import { connect } from 'react-redux'; -import { selectHasMLJob } from 'x-pack/plugins/apm/public/store/reactReduxRequest/transactionOverviewCharts'; -import { IReduxState } from 'x-pack/plugins/apm/public/store/rootReducer'; -import { selectIsMLAvailable } from 'x-pack/plugins/apm/public/store/selectors/license'; -import { TransactionChartsView } from './view'; - -const mapStateToProps = (state: IReduxState) => ({ - mlAvailable: selectIsMLAvailable(state), - hasMLJob: selectHasMLJob(state) -}); - -export const TransactionCharts = connect(mapStateToProps)( - TransactionChartsView +import { + EuiFlexGrid, + EuiFlexGroup, + EuiFlexItem, + EuiIconTip, + EuiPanel, + EuiText, + EuiTitle +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { Location } from 'history'; +import React, { Component } from 'react'; +import styled from 'styled-components'; +import { MLJobLink } from 'x-pack/plugins/apm/public/components/shared/Links/MLJobLink'; +import { ITransactionChartData } from 'x-pack/plugins/apm/public/store/selectors/chartSelectors'; +import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams'; +import { Coordinate } from 'x-pack/plugins/apm/typings/timeseries'; +import { asInteger, asMillis, tpmUnit } from '../../../../utils/formatters'; +import { LicenseContext } from '../../../app/Main/LicenseCheck'; +// @ts-ignore +import CustomPlot from '../CustomPlot'; +import { SyncChartGroup } from '../SyncChartGroup'; + +interface TransactionChartProps { + charts: ITransactionChartData; + location: Location; + urlParams: IUrlParams; +} + +const ShiftedIconWrapper = styled.span` + padding-right: 5px; + position: relative; + top: -1px; + display: inline-block; +`; + +const ShiftedEuiText = styled(EuiText)` + position: relative; + top: 5px; +`; + +const msTimeUnitLabel = i18n.translate( + 'xpack.apm.metrics.transactionChart.msTimeUnitLabel', + { + defaultMessage: 'ms' + } ); + +export class TransactionCharts extends Component { + public getResponseTimeTickFormatter = (t: number) => { + return this.props.charts.noHits ? `- ${msTimeUnitLabel}` : asMillis(t); + }; + + public getResponseTimeTooltipFormatter = (p: Coordinate) => { + return this.props.charts.noHits || !p + ? `- ${msTimeUnitLabel}` + : asMillis(p.y); + }; + + public getTPMFormatter = (t: number | null) => { + const { urlParams, charts } = this.props; + const unit = tpmUnit(urlParams.transactionType); + return charts.noHits || t === null + ? `- ${unit}` + : `${asInteger(t)} ${unit}`; + }; + + public getTPMTooltipFormatter = (p: Coordinate) => { + return this.getTPMFormatter(p.y); + }; + + public renderMLHeader(mlAvailable: boolean) { + const hasMLJob = this.props.charts.hasMLJob; + if (!mlAvailable || !hasMLJob) { + return null; + } + + const { serviceName, transactionType } = this.props.urlParams; + + if (!serviceName) { + return null; + } + + return ( + + + + = 75.' + } + )} + /> + + + {i18n.translate( + 'xpack.apm.metrics.transactionChart.machineLearningLabel', + { + defaultMessage: 'Machine learning:' + } + )}{' '} + + + View Job + + + + ); + } + + public render() { + const { charts, urlParams } = this.props; + const { noHits, responseTimeSeries, tpmSeries } = charts; + const { transactionType } = urlParams; + + return ( + ( + + + + + + + + {responseTimeLabel(transactionType)} + + + + {license => + this.renderMLHeader(license.features.ml.is_available) + } + + + + + + + + + + + + {tpmLabel(transactionType)} + + + + + + + )} + /> + ); + } +} + +function tpmLabel(type?: string) { + return type === 'request' + ? i18n.translate( + 'xpack.apm.metrics.transactionChart.requestsPerMinuteLabel', + { + defaultMessage: 'Requests per minute' + } + ) + : i18n.translate( + 'xpack.apm.metrics.transactionChart.transactionsPerMinuteLabel', + { + defaultMessage: 'Transactions per minute' + } + ); +} + +function responseTimeLabel(type?: string) { + switch (type) { + case 'page-load': + return i18n.translate( + 'xpack.apm.metrics.transactionChart.pageLoadTimesLabel', + { + defaultMessage: 'Page load times' + } + ); + case 'route-change': + return i18n.translate( + 'xpack.apm.metrics.transactionChart.routeChangeTimesLabel', + { + defaultMessage: 'Route change times' + } + ); + default: + return i18n.translate( + 'xpack.apm.metrics.transactionChart.transactionDurationLabel', + { + defaultMessage: 'Transaction duration' + } + ); + } +} diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/view.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/view.tsx deleted file mode 100644 index 1c4d79ed1e990..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/view.tsx +++ /dev/null @@ -1,224 +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 { - EuiFlexGrid, - EuiFlexGroup, - EuiFlexItem, - EuiIconTip, - EuiPanel, - EuiText, - EuiTitle -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { Location } from 'history'; -import React, { Component } from 'react'; -import styled from 'styled-components'; -import { MLJobLink } from 'x-pack/plugins/apm/public/components/shared/Links/MLJobLink'; -import { ITransactionChartData } from 'x-pack/plugins/apm/public/store/selectors/chartSelectors'; -import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams'; -import { Coordinate } from 'x-pack/plugins/apm/typings/timeseries'; -import { asInteger, asMillis, tpmUnit } from '../../../../utils/formatters'; -// @ts-ignore -import CustomPlot from '../CustomPlot'; -import { SyncChartGroup } from '../SyncChartGroup'; - -interface TransactionChartProps { - charts: ITransactionChartData; - chartWrapper?: React.ComponentClass | React.SFC; - location: Location; - urlParams: IUrlParams; - mlAvailable: boolean; - hasMLJob: boolean; -} - -const ShiftedIconWrapper = styled.span` - padding-right: 5px; - position: relative; - top: -1px; - display: inline-block; -`; - -const ShiftedEuiText = styled(EuiText)` - position: relative; - top: 5px; -`; - -const msTimeUnitLabel = i18n.translate( - 'xpack.apm.metrics.transactionChart.msTimeUnitLabel', - { - defaultMessage: 'ms' - } -); - -export class TransactionChartsView extends Component { - public getResponseTimeTickFormatter = (t: number) => { - return this.props.charts.noHits ? `- ${msTimeUnitLabel}` : asMillis(t); - }; - - public getResponseTimeTooltipFormatter = (p: Coordinate) => { - return this.props.charts.noHits || !p - ? `- ${msTimeUnitLabel}` - : asMillis(p.y); - }; - - public getTPMFormatter = (t: number | null) => { - const { urlParams, charts } = this.props; - const unit = tpmUnit(urlParams.transactionType); - return charts.noHits || t === null - ? `- ${unit}` - : `${asInteger(t)} ${unit}`; - }; - - public getTPMTooltipFormatter = (p: Coordinate) => { - return this.getTPMFormatter(p.y); - }; - - public renderMLHeader() { - if (!this.props.mlAvailable || !this.props.hasMLJob) { - return null; - } - - const { serviceName, transactionType } = this.props.urlParams; - - if (!serviceName) { - return null; - } - - return ( - - - - = 75.' - } - )} - /> - - - {i18n.translate( - 'xpack.apm.metrics.transactionChart.machineLearningLabel', - { - defaultMessage: 'Machine learning:' - } - )}{' '} - - - View Job - - - - ); - } - - public render() { - const { - charts, - urlParams, - chartWrapper: ChartWrapper = React.Fragment - } = this.props; - const { noHits, responseTimeSeries, tpmSeries } = charts; - const { transactionType } = urlParams; - - return ( - ( - - - - - - - - {responseTimeLabel(transactionType)} - - - {this.renderMLHeader()} - - - - - - - - - - - {tpmLabel(transactionType)} - - - - - - - )} - /> - ); - } -} - -function tpmLabel(type?: string) { - return type === 'request' - ? i18n.translate( - 'xpack.apm.metrics.transactionChart.requestsPerMinuteLabel', - { - defaultMessage: 'Requests per minute' - } - ) - : i18n.translate( - 'xpack.apm.metrics.transactionChart.transactionsPerMinuteLabel', - { - defaultMessage: 'Transactions per minute' - } - ); -} - -function responseTimeLabel(type?: string) { - switch (type) { - case 'page-load': - return i18n.translate( - 'xpack.apm.metrics.transactionChart.pageLoadTimesLabel', - { - defaultMessage: 'Page load times' - } - ); - case 'route-change': - return i18n.translate( - 'xpack.apm.metrics.transactionChart.routeChangeTimesLabel', - { - defaultMessage: 'Route change times' - } - ); - default: - return i18n.translate( - 'xpack.apm.metrics.transactionChart.transactionDurationLabel', - { - defaultMessage: 'Transaction duration' - } - ); - } -} diff --git a/x-pack/plugins/apm/public/hooks/useFetcher.integration.test.tsx b/x-pack/plugins/apm/public/hooks/useFetcher.integration.test.tsx new file mode 100644 index 0000000000000..6d4d0557bc27a --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/useFetcher.integration.test.tsx @@ -0,0 +1,121 @@ +/* + * 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 { render } from 'react-testing-library'; +import { delay, tick } from '../utils/testHelpers'; +import { useFetcher } from './useFetcher'; + +// Suppress warnings about "act" until async/await syntax is supported: https://github.com/facebook/react/issues/14769 +/* tslint:disable:no-console */ +const originalError = console.error; +beforeAll(() => { + console.error = jest.fn(); +}); +afterAll(() => { + console.error = originalError; +}); + +async function asyncFn(name: string, ms: number) { + await delay(ms); + return `Hello from ${name}`; +} + +describe('when simulating race condition', () => { + let requestCallOrder: Array<[string, string, number]>; + let renderSpy: jest.Mock; + + beforeEach(async () => { + jest.useFakeTimers(); + jest + .spyOn(window, 'requestAnimationFrame') + .mockImplementation(cb => cb(0) as any); + + renderSpy = jest.fn(); + requestCallOrder = []; + + function MyComponent({ + name, + ms, + renderFn + }: { + name: string; + ms: number; + renderFn: any; + }) { + const { data, status, error } = useFetcher( + async () => { + requestCallOrder.push(['request', name, ms]); + const res = await asyncFn(name, ms); + requestCallOrder.push(['response', name, ms]); + return res; + }, + [name, ms] + ); + renderFn({ data, status, error }); + return null; + } + + const { rerender } = render( + + ); + + rerender(); + }); + + it('should render initially render loading state', async () => { + expect(renderSpy).lastCalledWith({ + data: undefined, + error: undefined, + status: 'loading' + }); + }); + + it('should render "Hello from Peter" after 200ms', async () => { + jest.advanceTimersByTime(200); + await tick(); + + expect(renderSpy).lastCalledWith({ + data: 'Hello from Peter', + error: undefined, + status: 'success' + }); + }); + + it('should render "Hello from Peter" after 600ms', async () => { + jest.advanceTimersByTime(600); + await tick(); + + expect(renderSpy).lastCalledWith({ + data: 'Hello from Peter', + error: undefined, + status: 'success' + }); + }); + + it('should should NOT have rendered "Hello from John" at any point', async () => { + jest.advanceTimersByTime(600); + await tick(); + + expect(renderSpy).not.toHaveBeenCalledWith({ + data: 'Hello from John', + error: undefined, + status: 'success' + }); + }); + + it('should send and receive calls in the right order', async () => { + jest.advanceTimersByTime(600); + await tick(); + + expect(requestCallOrder).toEqual([ + ['request', 'John', 500], + ['request', 'Peter', 100], + ['response', 'Peter', 100], + ['response', 'John', 500] + ]); + }); +}); diff --git a/x-pack/plugins/apm/public/hooks/useFetcher.test.tsx b/x-pack/plugins/apm/public/hooks/useFetcher.test.tsx new file mode 100644 index 0000000000000..87722ce3c0275 --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/useFetcher.test.tsx @@ -0,0 +1,159 @@ +/* + * 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 { cleanup, renderHook } from 'react-hooks-testing-library'; +import { delay } from '../utils/testHelpers'; +import { useFetcher } from './useFetcher'; + +afterEach(cleanup); + +// Suppress warnings about "act" until async/await syntax is supported: https://github.com/facebook/react/issues/14769 +/* tslint:disable:no-console */ +const originalError = console.error; +beforeAll(() => { + console.error = jest.fn(); +}); +afterAll(() => { + console.error = originalError; +}); + +describe('useFetcher', () => { + describe('when resolving after 500ms', () => { + let hook: ReturnType; + beforeEach(() => { + jest.useFakeTimers(); + async function fn() { + await delay(500); + return 'response from hook'; + } + hook = renderHook(() => useFetcher(() => fn(), [])); + }); + + it('should initially be empty', async () => { + expect(hook.result.current).toEqual({ + data: undefined, + error: undefined, + status: undefined + }); + }); + + it('should show loading spinner after 100ms', async () => { + jest.advanceTimersByTime(100); + await hook.waitForNextUpdate(); + + expect(hook.result.current).toEqual({ + data: undefined, + error: undefined, + status: 'loading' + }); + }); + + it('should show success after 1 second', async () => { + jest.advanceTimersByTime(1000); + await hook.waitForNextUpdate(); + + expect(hook.result.current).toEqual({ + data: 'response from hook', + error: undefined, + status: 'success' + }); + }); + }); + + describe('when throwing after 500ms', () => { + let hook: ReturnType; + beforeEach(() => { + jest.useFakeTimers(); + async function fn() { + await delay(500); + throw new Error('Something went wrong'); + } + hook = renderHook(() => useFetcher(() => fn(), [])); + }); + + it('should initially be empty', async () => { + expect(hook.result.current).toEqual({ + data: undefined, + error: undefined, + status: undefined + }); + }); + + it('should show loading spinner after 100ms', async () => { + jest.advanceTimersByTime(100); + await hook.waitForNextUpdate(); + + expect(hook.result.current).toEqual({ + data: undefined, + error: undefined, + status: 'loading' + }); + }); + + it('should show error after 1 second', async () => { + jest.advanceTimersByTime(1000); + await hook.waitForNextUpdate(); + + expect(hook.result.current).toEqual({ + data: undefined, + error: expect.any(Error), + status: 'failure' + }); + }); + }); + + describe('when a hook already has data', () => { + it('should show "first response" while loading "second response"', async () => { + jest.useFakeTimers(); + const hook = renderHook( + ({ callback, args }) => useFetcher(callback, args), + { + initialProps: { + callback: async () => 'first response', + args: ['a'] + } + } + ); + await hook.waitForNextUpdate(); + + // assert: first response has loaded and should be rendered + expect(hook.result.current).toEqual({ + data: 'first response', + error: undefined, + status: 'success' + }); + + // act: re-render hook with async callback + hook.rerender({ + callback: async () => { + await delay(500); + return 'second response'; + }, + args: ['b'] + }); + + jest.advanceTimersByTime(100); + await hook.waitForNextUpdate(); + + // assert: while loading new data the previous data should still be rendered + expect(hook.result.current).toEqual({ + data: 'first response', + error: undefined, + status: 'loading' + }); + + jest.advanceTimersByTime(500); + await hook.waitForNextUpdate(); + + // assert: "second response" has loaded and should be rendered + expect(hook.result.current).toEqual({ + data: 'second response', + error: undefined, + status: 'success' + }); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/hooks/useFetcher.tsx b/x-pack/plugins/apm/public/hooks/useFetcher.tsx new file mode 100644 index 0000000000000..6022f8bb75853 --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/useFetcher.tsx @@ -0,0 +1,83 @@ +/* + * 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 { useContext, useEffect, useState } from 'react'; +import { GlobalFetchContext } from '../components/app/Main/GlobalFetchIndicator'; + +export enum FETCH_STATUS { + LOADING = 'loading', + SUCCESS = 'success', + FAILURE = 'failure' +} + +// use this in request methods to signal to `useFetch` that all arguments are not yet available +export class MissingArgumentsError extends Error {} + +export function useFetcher( + fn: () => Promise, + useEffectKey: Array +) { + const { dispatchStatus } = useContext(GlobalFetchContext); + const [result, setResult] = useState<{ + data?: Response; + status?: FETCH_STATUS; + error?: Error; + }>({}); + + useEffect(() => { + let didCancel = false; + let didFinish = false; + + // only apply the loading indicator if the promise did not resolve immediately + // the promise will resolve immediately if the value was found in cache + requestAnimationFrame(() => { + if (!didFinish && !didCancel) { + dispatchStatus({ name: fn.name, isLoading: true }); + setResult({ + data: result.data, // preserve data from previous state while loading next state + status: FETCH_STATUS.LOADING, + error: undefined + }); + } + }); + + async function doFetch() { + try { + const data = await fn(); + if (!didCancel) { + dispatchStatus({ name: fn.name, isLoading: false }); + setResult({ + data, + status: FETCH_STATUS.SUCCESS, + error: undefined + }); + } + } catch (e) { + if (e instanceof MissingArgumentsError) { + return; + } + if (!didCancel) { + dispatchStatus({ name: fn.name, isLoading: false }); + setResult({ + data: undefined, + status: FETCH_STATUS.FAILURE, + error: e + }); + } + } + didFinish = true; + } + + doFetch(); + + return () => { + dispatchStatus({ name: fn.name, isLoading: false }); + didCancel = true; + }; + }, useEffectKey); + + return result || {}; +} diff --git a/x-pack/plugins/apm/public/hooks/useServiceMetricCharts.ts b/x-pack/plugins/apm/public/hooks/useServiceMetricCharts.ts new file mode 100644 index 0000000000000..040ac6efa59d8 --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/useServiceMetricCharts.ts @@ -0,0 +1,85 @@ +/* + * 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 { useMemo } from 'react'; +import { MetricsChartAPIResponse } from '../../server/lib/metrics/get_all_metrics_chart_data'; +import { MemoryChartAPIResponse } from '../../server/lib/metrics/get_memory_chart_data'; +import { loadMetricsChartDataForService } from '../services/rest/apm/metrics'; +import { + getCPUSeries, + getMemorySeries +} from '../store/selectors/chartSelectors'; +import { IUrlParams } from '../store/urlParams'; +import { useFetcher } from './useFetcher'; + +const memory: MemoryChartAPIResponse = { + series: { + memoryUsedAvg: [], + memoryUsedMax: [] + }, + overallValues: { + memoryUsedAvg: null, + memoryUsedMax: null + }, + totalHits: 0 +}; + +const INITIAL_DATA: MetricsChartAPIResponse = { + memory, + cpu: { + series: { + systemCPUAverage: [], + systemCPUMax: [], + processCPUAverage: [], + processCPUMax: [] + }, + overallValues: { + systemCPUAverage: null, + systemCPUMax: null, + processCPUAverage: null, + processCPUMax: null + }, + totalHits: 0 + } +}; + +export function useServiceMetricCharts(urlParams: IUrlParams) { + const { + serviceName, + transactionType, + start, + end, + transactionName, + kuery + } = urlParams; + + const { data = INITIAL_DATA, error, status } = useFetcher( + () => + loadMetricsChartDataForService({ + serviceName, + transactionName, + transactionType, + start, + end, + kuery + }), + [serviceName, transactionName, transactionType, start, end, kuery] + ); + + const memoizedData = useMemo( + () => ({ + memory: getMemorySeries(urlParams, data.memory), + cpu: getCPUSeries(data.cpu) + }), + [data] + ); + + return { + data: memoizedData, + status, + error + }; +} diff --git a/x-pack/plugins/apm/public/hooks/useTransactionDetailsCharts.ts b/x-pack/plugins/apm/public/hooks/useTransactionDetailsCharts.ts new file mode 100644 index 0000000000000..7a9adfc55035a --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/useTransactionDetailsCharts.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useMemo } from 'react'; +import { loadTransactionDetailsCharts } from '../services/rest/apm/transaction_groups'; +import { getTransactionCharts } from '../store/selectors/chartSelectors'; +import { IUrlParams } from '../store/urlParams'; +import { useFetcher } from './useFetcher'; + +export function useTransactionDetailsCharts(urlParams: IUrlParams) { + const { + serviceName, + transactionType, + start, + end, + transactionName, + kuery + } = urlParams; + + const { data, error, status } = useFetcher( + () => + loadTransactionDetailsCharts({ + serviceName, + transactionName, + transactionType, + start, + end, + kuery + }), + [serviceName, transactionName, transactionType, start, end, kuery] + ); + + const memoizedData = useMemo(() => getTransactionCharts(urlParams, data), [ + data + ]); + + return { + data: memoizedData, + status, + error + }; +} diff --git a/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts b/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts new file mode 100644 index 0000000000000..815d709ebfdb2 --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts @@ -0,0 +1,50 @@ +/* + * 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 { loadTransactionDistribution } from '../services/rest/apm/transaction_groups'; +import { IUrlParams } from '../store/urlParams'; +import { useFetcher } from './useFetcher'; + +const INITIAL_DATA = { buckets: [], totalHits: 0, bucketSize: 0 }; + +export function useTransactionDistribution(urlParams: IUrlParams) { + const { + serviceName, + transactionType, + transactionId, + traceId, + start, + end, + transactionName, + kuery + } = urlParams; + + const { data = INITIAL_DATA, status, error } = useFetcher( + () => + loadTransactionDistribution({ + serviceName, + transactionType, + transactionId, + traceId, + start, + end, + transactionName, + kuery + }), + [ + serviceName, + transactionType, + transactionId, + traceId, + start, + end, + transactionName, + kuery + ] + ); + + return { data, status, error }; +} diff --git a/x-pack/plugins/apm/public/hooks/useTransactionList.ts b/x-pack/plugins/apm/public/hooks/useTransactionList.ts new file mode 100644 index 0000000000000..fa04aca4280e0 --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/useTransactionList.ts @@ -0,0 +1,50 @@ +/* + * 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 { useMemo } from 'react'; +import { TransactionListAPIResponse } from '../../server/lib/transactions/get_top_transactions'; +import { loadTransactionList } from '../services/rest/apm/transaction_groups'; +import { IUrlParams } from '../store/urlParams'; +import { useFetcher } from './useFetcher'; + +const getRelativeImpact = ( + impact: number, + impactMin: number, + impactMax: number +) => + Math.max( + ((impact - impactMin) / Math.max(impactMax - impactMin, 1)) * 100, + 1 + ); + +function getWithRelativeImpact(items: TransactionListAPIResponse) { + const impacts = items.map(({ impact }) => impact); + const impactMin = Math.min(...impacts); + const impactMax = Math.max(...impacts); + + return items.map(item => { + return { + ...item, + impactRelative: getRelativeImpact(item.impact, impactMin, impactMax) + }; + }); +} + +export function useTransactionList(urlParams: IUrlParams) { + const { serviceName, transactionType, start, end, kuery } = urlParams; + const { data = [], error, status } = useFetcher( + () => + loadTransactionList({ serviceName, start, end, transactionType, kuery }), + [serviceName, start, end, transactionType, kuery] + ); + + const memoizedData = useMemo(() => getWithRelativeImpact(data), [data]); + return { + data: memoizedData, + status, + error + }; +} diff --git a/x-pack/plugins/apm/public/hooks/useTransactionOverviewCharts.ts b/x-pack/plugins/apm/public/hooks/useTransactionOverviewCharts.ts new file mode 100644 index 0000000000000..20779069680cb --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/useTransactionOverviewCharts.ts @@ -0,0 +1,44 @@ +/* + * 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 { useMemo } from 'react'; +import { loadTransactionOverviewCharts } from '../services/rest/apm/transaction_groups'; +import { getTransactionCharts } from '../store/selectors/chartSelectors'; +import { IUrlParams } from '../store/urlParams'; +import { useFetcher } from './useFetcher'; + +export function useTransactionOverviewCharts(urlParams: IUrlParams) { + const { + serviceName, + transactionType, + start, + end, + + kuery + } = urlParams; + + const { data, error, status } = useFetcher( + () => + loadTransactionOverviewCharts({ + serviceName, + start, + end, + transactionType, + kuery + }), + [serviceName, start, end, transactionType, kuery] + ); + + const memoizedData = useMemo(() => getTransactionCharts(urlParams, data), [ + data + ]); + + return { + data: memoizedData, + status, + error + }; +} diff --git a/x-pack/plugins/apm/public/hooks/useWaterfall.ts b/x-pack/plugins/apm/public/hooks/useWaterfall.ts new file mode 100644 index 0000000000000..d3b23fa2f156b --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/useWaterfall.ts @@ -0,0 +1,28 @@ +/* + * 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 { useMemo } from 'react'; +import { getWaterfall } from '../components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers'; +import { loadTrace } from '../services/rest/apm/traces'; +import { IUrlParams } from '../store/urlParams'; +import { useFetcher } from './useFetcher'; + +const INITIAL_DATA = { trace: [], errorsPerTransaction: {} }; + +export function useWaterfall(urlParams: IUrlParams) { + const { traceId, start, end, transactionId } = urlParams; + const { data = INITIAL_DATA, status, error } = useFetcher( + () => loadTrace({ traceId, start, end }), + [traceId, start, end] + ); + + const waterfall = useMemo(() => getWaterfall(data, transactionId), [ + data, + transactionId + ]); + + return { data: waterfall, status, error }; +} diff --git a/x-pack/plugins/apm/public/index.tsx b/x-pack/plugins/apm/public/index.tsx index 1c7a154ee7f10..3779776c54e0c 100644 --- a/x-pack/plugins/apm/public/index.tsx +++ b/x-pack/plugins/apm/public/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment } from 'react'; +import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { Router } from 'react-router-dom'; @@ -18,7 +18,6 @@ import { uiModules } from 'ui/modules'; import 'uiExports/autocompleteProviders'; import { GlobalHelpExtension } from './components/app/GlobalHelpExtension'; import { Main } from './components/app/Main'; -import { GlobalProgress } from './components/app/Main/GlobalProgress'; import { history } from './components/shared/Links/url_helpers'; // @ts-ignore import configureStore from './store/config/configureStore'; @@ -53,12 +52,9 @@ waitForRoot.then(() => { ReactDOM.render( - - - -
    - - + +
    + , document.getElementById(REACT_APP_ROOT_ID) diff --git a/x-pack/plugins/apm/public/services/__test__/callApi.test.ts b/x-pack/plugins/apm/public/services/__test__/callApi.test.ts index 0d2183b469821..b28287ab9d630 100644 --- a/x-pack/plugins/apm/public/services/__test__/callApi.test.ts +++ b/x-pack/plugins/apm/public/services/__test__/callApi.test.ts @@ -5,7 +5,8 @@ */ import * as kfetchModule from 'ui/kfetch'; -import { callApi } from '../rest/callApi'; +import { mockNow } from '../../utils/testHelpers'; +import { _clearCache, callApi } from '../rest/callApi'; import { SessionStorageMock } from './SessionStorageMock'; describe('callApi', () => { @@ -21,41 +22,148 @@ describe('callApi', () => { afterEach(() => { kfetchSpy.mockClear(); + _clearCache(); }); - describe('callApi', () => { - describe('apm_debug', () => { - beforeEach(() => { - sessionStorage.setItem('apm_debug', 'true'); + describe('apm_debug', () => { + beforeEach(() => { + sessionStorage.setItem('apm_debug', 'true'); + }); + + it('should add debug param for APM endpoints', async () => { + await callApi({ pathname: `/api/apm/status/server` }); + + expect(kfetchSpy).toHaveBeenCalledWith( + { pathname: '/api/apm/status/server', query: { _debug: true } }, + undefined + ); + }); + + it('should not add debug param for non-APM endpoints', async () => { + await callApi({ pathname: `/api/kibana` }); + + expect(kfetchSpy).toHaveBeenCalledWith( + { pathname: '/api/kibana' }, + undefined + ); + }); + }); + + describe('prependBasePath', () => { + it('should be passed on to kFetch', async () => { + await callApi({ pathname: `/api/kibana` }, { prependBasePath: false }); + + expect(kfetchSpy).toHaveBeenCalledWith( + { pathname: '/api/kibana' }, + { prependBasePath: false } + ); + }); + }); + + describe('cache', () => { + let nowSpy: jest.Mock; + beforeEach(() => { + nowSpy = mockNow('2019'); + }); + + beforeEach(() => { + nowSpy.mockRestore(); + }); + + describe('when the call does not contain start/end params', () => { + it('should not return cached response for identical calls', async () => { + await callApi({ pathname: `/api/kibana`, query: { foo: 'bar' } }); + await callApi({ pathname: `/api/kibana`, query: { foo: 'bar' } }); + await callApi({ pathname: `/api/kibana`, query: { foo: 'bar' } }); + + expect(kfetchSpy).toHaveBeenCalledTimes(3); }); + }); - it('should add debug param for APM endpoints', async () => { - await callApi({ pathname: `/api/apm/status/server` }); + describe('when the call contains start/end params', () => { + it('should return cached response for identical calls', async () => { + await callApi({ + pathname: `/api/kibana`, + query: { start: '2010', end: '2011' } + }); + await callApi({ + pathname: `/api/kibana`, + query: { start: '2010', end: '2011' } + }); + await callApi({ + pathname: `/api/kibana`, + query: { start: '2010', end: '2011' } + }); - expect(kfetchSpy).toHaveBeenCalledWith( - { pathname: '/api/apm/status/server', query: { _debug: true } }, - undefined - ); + expect(kfetchSpy).toHaveBeenCalledTimes(1); }); - it('should not add debug param for non-APM endpoints', async () => { - await callApi({ pathname: `/api/kibana` }); + it('should not return cached response for subsequent calls if arguments change', async () => { + await callApi({ + pathname: `/api/kibana`, + query: { start: '2010', end: '2011', foo: 'bar1' } + }); + await callApi({ + pathname: `/api/kibana`, + query: { start: '2010', end: '2011', foo: 'bar2' } + }); + await callApi({ + pathname: `/api/kibana`, + query: { start: '2010', end: '2011', foo: 'bar3' } + }); - expect(kfetchSpy).toHaveBeenCalledWith( - { pathname: '/api/kibana' }, - undefined - ); + expect(kfetchSpy).toHaveBeenCalledTimes(3); + }); + + it('should not return cached response if `end` is a future timestamp', async () => { + await callApi({ + pathname: `/api/kibana`, + query: { end: '2030' } + }); + await callApi({ + pathname: `/api/kibana`, + query: { end: '2030' } + }); + await callApi({ + pathname: `/api/kibana`, + query: { end: '2030' } + }); + + expect(kfetchSpy).toHaveBeenCalledTimes(3); + }); + + it('should return cached response if calls contain `end` param in the past', async () => { + await callApi({ + pathname: `/api/kibana`, + query: { start: '2009', end: '2010' } + }); + await callApi({ + pathname: `/api/kibana`, + query: { start: '2009', end: '2010' } + }); + await callApi({ + pathname: `/api/kibana`, + query: { start: '2009', end: '2010' } + }); + + expect(kfetchSpy).toHaveBeenCalledTimes(1); }); - }); - describe('prependBasePath', () => { - it('should be passed on to kFetch', async () => { - await callApi({ pathname: `/api/kibana` }, { prependBasePath: false }); + it('should return cached response even if order of properties change', async () => { + await callApi({ + pathname: `/api/kibana`, + query: { end: '2010', start: '2009' } + }); + await callApi({ + pathname: `/api/kibana`, + query: { start: '2009', end: '2010' } + }); + await callApi({ + query: { start: '2009', end: '2010' }, + pathname: `/api/kibana` + }); - expect(kfetchSpy).toHaveBeenCalledWith( - { pathname: '/api/kibana' }, - { prependBasePath: false } - ); + expect(kfetchSpy).toHaveBeenCalledTimes(1); }); }); }); diff --git a/x-pack/plugins/apm/public/services/rest/apm/error_groups.ts b/x-pack/plugins/apm/public/services/rest/apm/error_groups.ts index 0edfaf3495f12..02008a3ceac95 100644 --- a/x-pack/plugins/apm/public/services/rest/apm/error_groups.ts +++ b/x-pack/plugins/apm/public/services/rest/apm/error_groups.ts @@ -7,29 +7,27 @@ import { ErrorDistributionAPIResponse } from 'x-pack/plugins/apm/server/lib/errors/distribution/get_distribution'; import { ErrorGroupAPIResponse } from 'x-pack/plugins/apm/server/lib/errors/get_error_group'; import { ErrorGroupListAPIResponse } from 'x-pack/plugins/apm/server/lib/errors/get_error_groups'; +import { MissingArgumentsError } from '../../../hooks/useFetcher'; import { IUrlParams } from '../../../store/urlParams'; import { callApi } from '../callApi'; import { getEncodedEsQuery } from './apm'; -interface ErrorGroupListParams extends IUrlParams { - size: number; -} - export async function loadErrorGroupList({ serviceName, start, end, kuery, - size, sortField, sortDirection -}: ErrorGroupListParams) { +}: IUrlParams) { + if (!(serviceName && start && end)) { + throw new MissingArgumentsError(); + } return callApi({ pathname: `/api/apm/services/${serviceName}/errors`, query: { start, end, - size, sortField, sortDirection, esFilterQuery: await getEncodedEsQuery(kuery) @@ -44,6 +42,9 @@ export async function loadErrorGroupDetails({ kuery, errorGroupId }: IUrlParams) { + if (!(serviceName && start && end && errorGroupId)) { + throw new MissingArgumentsError(); + } return callApi({ pathname: `/api/apm/services/${serviceName}/errors/${errorGroupId}`, query: { @@ -61,6 +62,10 @@ export async function loadErrorDistribution({ kuery, errorGroupId }: IUrlParams) { + if (!(serviceName && start && end)) { + throw new MissingArgumentsError(); + } + const pathname = errorGroupId ? `/api/apm/services/${serviceName}/errors/${errorGroupId}/distribution` : `/api/apm/services/${serviceName}/errors/distribution`; diff --git a/x-pack/plugins/apm/public/services/rest/apm/metrics.ts b/x-pack/plugins/apm/public/services/rest/apm/metrics.ts index 37c8cf0e918b9..bfeee4c1f289a 100644 --- a/x-pack/plugins/apm/public/services/rest/apm/metrics.ts +++ b/x-pack/plugins/apm/public/services/rest/apm/metrics.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { MetricsChartAPIResponse } from 'x-pack/plugins/apm/server/lib/metrics/get_all_metrics_chart_data'; import { IUrlParams } from '../../../store/urlParams'; import { callApi } from '../callApi'; import { getEncodedEsQuery } from './apm'; @@ -14,7 +15,7 @@ export async function loadMetricsChartDataForService({ end, kuery }: IUrlParams) { - return callApi({ + return callApi({ pathname: `/api/apm/services/${serviceName}/metrics/charts`, query: { start, diff --git a/x-pack/plugins/apm/public/services/rest/apm/services.ts b/x-pack/plugins/apm/public/services/rest/apm/services.ts index 430d2fa21770b..0af17d58813ad 100644 --- a/x-pack/plugins/apm/public/services/rest/apm/services.ts +++ b/x-pack/plugins/apm/public/services/rest/apm/services.ts @@ -6,11 +6,16 @@ import { ServiceAPIResponse } from 'x-pack/plugins/apm/server/lib/services/get_service'; import { ServiceListAPIResponse } from 'x-pack/plugins/apm/server/lib/services/get_services'; +import { MissingArgumentsError } from '../../../hooks/useFetcher'; import { IUrlParams } from '../../../store/urlParams'; import { callApi } from '../callApi'; import { getEncodedEsQuery } from './apm'; export async function loadServiceList({ start, end, kuery }: IUrlParams) { + if (!(start && end)) { + throw new MissingArgumentsError(); + } + return callApi({ pathname: `/api/apm/services`, query: { @@ -27,6 +32,10 @@ export async function loadServiceDetails({ end, kuery }: IUrlParams) { + if (!(serviceName && start && end)) { + throw new MissingArgumentsError(); + } + return callApi({ pathname: `/api/apm/services/${serviceName}`, query: { diff --git a/x-pack/plugins/apm/public/services/rest/apm/status_check.ts b/x-pack/plugins/apm/public/services/rest/apm/status_check.ts index 30fe628d8e7f4..0c6b660930b41 100644 --- a/x-pack/plugins/apm/public/services/rest/apm/status_check.ts +++ b/x-pack/plugins/apm/public/services/rest/apm/status_check.ts @@ -13,7 +13,9 @@ export async function loadServerStatus() { } export async function loadAgentStatus() { - return callApi<{ dataFound: boolean }>({ + const res = await callApi<{ dataFound: boolean }>({ pathname: `/api/apm/status/agent` }); + + return res.dataFound; } diff --git a/x-pack/plugins/apm/public/services/rest/apm/traces.ts b/x-pack/plugins/apm/public/services/rest/apm/traces.ts index 1a681ecc3ade4..75d2f3af9308b 100644 --- a/x-pack/plugins/apm/public/services/rest/apm/traces.ts +++ b/x-pack/plugins/apm/public/services/rest/apm/traces.ts @@ -6,11 +6,16 @@ import { TraceListAPIResponse } from 'x-pack/plugins/apm/server/lib/traces/get_top_traces'; import { TraceAPIResponse } from 'x-pack/plugins/apm/server/lib/traces/get_trace'; +import { MissingArgumentsError } from '../../../hooks/useFetcher'; import { IUrlParams } from '../../../store/urlParams'; import { callApi } from '../callApi'; import { getEncodedEsQuery } from './apm'; export async function loadTrace({ traceId, start, end }: IUrlParams) { + if (!(traceId && start && end)) { + throw new MissingArgumentsError(); + } + return callApi({ pathname: `/api/apm/traces/${traceId}`, query: { @@ -21,6 +26,10 @@ export async function loadTrace({ traceId, start, end }: IUrlParams) { } export async function loadTraceList({ start, end, kuery }: IUrlParams) { + if (!(start && end)) { + throw new MissingArgumentsError(); + } + return callApi({ pathname: '/api/apm/traces', query: { diff --git a/x-pack/plugins/apm/public/services/rest/apm/transaction_groups.ts b/x-pack/plugins/apm/public/services/rest/apm/transaction_groups.ts index 53025a0daf685..a5be968852334 100644 --- a/x-pack/plugins/apm/public/services/rest/apm/transaction_groups.ts +++ b/x-pack/plugins/apm/public/services/rest/apm/transaction_groups.ts @@ -7,6 +7,7 @@ import { TimeSeriesAPIResponse } from 'x-pack/plugins/apm/server/lib/transactions/charts'; import { ITransactionDistributionAPIResponse } from 'x-pack/plugins/apm/server/lib/transactions/distribution'; import { TransactionListAPIResponse } from 'x-pack/plugins/apm/server/lib/transactions/get_top_transactions'; +import { MissingArgumentsError } from '../../../hooks/useFetcher'; import { IUrlParams } from '../../../store/urlParams'; import { callApi } from '../callApi'; import { getEncodedEsQuery } from './apm'; @@ -16,8 +17,12 @@ export async function loadTransactionList({ start, end, kuery, - transactionType = 'request' + transactionType }: IUrlParams) { + if (!(serviceName && transactionType && start && end)) { + throw new MissingArgumentsError(); + } + return await callApi({ pathname: `/api/apm/services/${serviceName}/transaction_groups/${transactionType}`, query: { @@ -33,11 +38,15 @@ export async function loadTransactionDistribution({ start, end, transactionName, - transactionType = 'request', + transactionType, transactionId, traceId, kuery -}: Required) { +}: IUrlParams) { + if (!(serviceName && transactionName && transactionType && start && end)) { + throw new MissingArgumentsError(); + } + return callApi({ pathname: `/api/apm/services/${serviceName}/transaction_groups/${transactionType}/${encodeURIComponent( transactionName @@ -52,14 +61,18 @@ export async function loadTransactionDistribution({ }); } -export async function loadDetailsCharts({ +export async function loadTransactionDetailsCharts({ serviceName, start, end, kuery, - transactionType = 'request', + transactionType, transactionName -}: Required) { +}: IUrlParams) { + if (!(serviceName && transactionName && transactionType && start && end)) { + throw new MissingArgumentsError(); + } + return callApi({ pathname: `/api/apm/services/${serviceName}/transaction_groups/${transactionType}/${encodeURIComponent( transactionName @@ -72,31 +85,23 @@ export async function loadDetailsCharts({ }); } -export async function loadOverviewCharts({ +export async function loadTransactionOverviewCharts({ serviceName, start, end, kuery, - transactionType = 'request' + transactionType }: IUrlParams) { - return callApi({ - pathname: `/api/apm/services/${serviceName}/transaction_groups/${transactionType}/charts`, - query: { - start, - end, - esFilterQuery: await getEncodedEsQuery(kuery) - } - }); -} + if (!(serviceName && start && end)) { + throw new MissingArgumentsError(); + } + + const pathname = transactionType + ? `/api/apm/services/${serviceName}/transaction_groups/${transactionType}/charts` + : `/api/apm/services/${serviceName}/transaction_groups/charts`; -export async function loadOverviewChartsForAllTypes({ - serviceName, - start, - end, - kuery -}: IUrlParams) { return callApi({ - pathname: `/api/apm/services/${serviceName}/transaction_groups/charts`, + pathname, query: { start, end, diff --git a/x-pack/plugins/apm/public/services/rest/callApi.ts b/x-pack/plugins/apm/public/services/rest/callApi.ts index 26fea4f17e9cb..27842a19a322a 100644 --- a/x-pack/plugins/apm/public/services/rest/callApi.ts +++ b/x-pack/plugins/apm/public/services/rest/callApi.ts @@ -4,7 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { startsWith } from 'lodash'; +import { FetchOptions } from 'apollo-link-http'; +import { isString, startsWith } from 'lodash'; +import LRU from 'lru-cache'; +import hash from 'object-hash'; import { kfetch, KFetchOptions } from 'ui/kfetch'; import { KFetchKibanaOptions } from 'ui/kfetch/kfetch'; @@ -26,10 +29,49 @@ function fetchOptionsWithDebug(fetchOptions: KFetchOptions) { }; } +const cache = new LRU({ max: 100, maxAge: 1000 * 60 * 60 }); + +export function _clearCache() { + cache.reset(); +} + export async function callApi( fetchOptions: KFetchOptions, options?: KFetchKibanaOptions ): Promise { + const cacheKey = getCacheKey(fetchOptions); + const cacheResponse = cache.get(cacheKey); + if (cacheResponse) { + return cacheResponse; + } + const combinedFetchOptions = fetchOptionsWithDebug(fetchOptions); - return await kfetch(combinedFetchOptions, options); + const res = await kfetch(combinedFetchOptions, options); + + if (isCachable(fetchOptions)) { + cache.set(cacheKey, res); + } + + return res; +} + +// only cache items that has a time range with `start` and `end` params, +// and where `end` is not a timestamp in the future +function isCachable(fetchOptions: KFetchOptions) { + if ( + !(fetchOptions.query && fetchOptions.query.start && fetchOptions.query.end) + ) { + return false; + } + + return ( + isString(fetchOptions.query.end) && + new Date(fetchOptions.query.end).getTime() < Date.now() + ); +} + +// order the options object to make sure that two objects with the same arguments, produce produce the +// same cache key regardless of the order of properties +function getCacheKey(options: FetchOptions) { + return hash(options); } diff --git a/x-pack/plugins/apm/public/store/__jest__/rootReducer.test.ts b/x-pack/plugins/apm/public/store/__jest__/rootReducer.test.ts index 0eb91fc267b47..17c0f941079a9 100644 --- a/x-pack/plugins/apm/public/store/__jest__/rootReducer.test.ts +++ b/x-pack/plugins/apm/public/store/__jest__/rootReducer.test.ts @@ -12,7 +12,6 @@ describe('root reducer', () => { expect(state).toEqual({ location: { hash: '', pathname: '', search: '' }, - reactReduxRequest: {}, urlParams: {} }); }); diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/__jest__/helpers.test.js b/x-pack/plugins/apm/public/store/reactReduxRequest/__jest__/helpers.test.js deleted file mode 100644 index 5ed1bb04651b1..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/__jest__/helpers.test.js +++ /dev/null @@ -1,31 +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 { createInitialDataSelector } from '../helpers'; - -describe('createInitialDataSelector', () => { - it('should use initialData when data is missing from state', () => { - const state = {}; - const initialData = { foo: 'bar' }; - const withInitialData = createInitialDataSelector(initialData); - - expect(withInitialData(state)).toBe(withInitialData(state)); - expect(withInitialData(state, initialData)).toEqual({ - data: { foo: 'bar' } - }); - }); - - it('should use data when available', () => { - const state = { data: 'hello' }; - const initialData = { foo: 'bar' }; - const withInitialData = createInitialDataSelector(initialData); - - expect(withInitialData(state)).toBe(withInitialData(state)); - expect(withInitialData(state, initialData)).toEqual({ - data: 'hello' - }); - }); -}); diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/__jest__/serviceList.test.js b/x-pack/plugins/apm/public/store/reactReduxRequest/__jest__/serviceList.test.js deleted file mode 100644 index b45d3bbc76b1c..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/__jest__/serviceList.test.js +++ /dev/null @@ -1,71 +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 React from 'react'; -import * as rest from '../../../services/rest/apm/services'; -import { getServiceList, ServiceListRequest } from '../serviceList'; -import { mountWithStore } from '../../../utils/testHelpers'; - -describe('serviceList', () => { - describe('getServiceList', () => { - it('should return default value when empty', () => { - const state = { reactReduxRequest: {}, sorting: { service: {} } }; - expect(getServiceList(state)).toEqual({ data: [] }); - }); - - it('should return serviceList when not empty', () => { - const state = { - reactReduxRequest: { serviceList: { data: [{ foo: 'bar' }] } }, - sorting: { service: {} } - }; - expect(getServiceList(state)).toEqual({ data: [{ foo: 'bar' }] }); - }); - }); - - describe('ServiceListRequest', () => { - let loadSpy; - let renderSpy; - let wrapper; - - beforeEach(() => { - const state = { - reactReduxRequest: { - serviceList: { status: 'my-status', data: [{ foo: 'bar' }] } - }, - sorting: { service: {} } - }; - - loadSpy = jest.spyOn(rest, 'loadServiceList').mockReturnValue(); - renderSpy = jest.fn().mockReturnValue(
    rendered
    ); - - wrapper = mountWithStore( - , - state - ); - }); - - it('should call render method', () => { - expect(renderSpy).toHaveBeenCalledWith({ - data: [{ foo: 'bar' }], - status: 'my-status' - }); - }); - - it('should call "loadServiceList"', () => { - expect(loadSpy).toHaveBeenCalledWith({ - start: 'myStart', - end: 'myEnd' - }); - }); - - it('should render component', () => { - expect(wrapper.html()).toEqual('
    rendered
    '); - }); - }); -}); diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/errorDistribution.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/errorDistribution.tsx deleted file mode 100644 index ef91d06bfad6e..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/errorDistribution.tsx +++ /dev/null @@ -1,49 +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 React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { ErrorDistributionAPIResponse } from 'x-pack/plugins/apm/server/lib/errors/distribution/get_distribution'; -import { loadErrorDistribution } from '../../services/rest/apm/error_groups'; -import { IReduxState } from '../rootReducer'; -import { IUrlParams } from '../urlParams'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'errorDistribution'; -const INITIAL_DATA: ErrorDistributionAPIResponse = { - buckets: [], - totalHits: 0, - bucketSize: 0 -}; -const withInitialData = createInitialDataSelector(INITIAL_DATA); - -export function getErrorDistribution(state: IReduxState) { - return withInitialData(state.reactReduxRequest[ID]); -} - -export function ErrorDistributionRequest({ - urlParams, - render -}: { - urlParams: IUrlParams; - render: RRRRender; -}) { - const { serviceName, start, end, errorGroupId, kuery } = urlParams; - - if (!(serviceName && start && end)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroup.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroup.tsx deleted file mode 100644 index 37e1983c0a2a8..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroup.tsx +++ /dev/null @@ -1,45 +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 React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { ErrorGroupAPIResponse } from 'x-pack/plugins/apm/server/lib/errors/get_error_group'; -import { loadErrorGroupDetails } from '../../services/rest/apm/error_groups'; -import { IReduxState } from '../rootReducer'; -import { IUrlParams } from '../urlParams'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'errorGroupDetails'; -const INITIAL_DATA: ErrorGroupAPIResponse = { occurrencesCount: 0 }; -const withInitialData = createInitialDataSelector(INITIAL_DATA); - -export function getErrorGroupDetails(state: IReduxState) { - return withInitialData(state.reactReduxRequest[ID]); -} - -export function ErrorGroupDetailsRequest({ - urlParams, - render -}: { - urlParams: IUrlParams; - render: RRRRender; -}) { - const { serviceName, errorGroupId, start, end, kuery } = urlParams; - - if (!(serviceName && start && end && errorGroupId)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroupList.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroupList.tsx deleted file mode 100644 index b7c3daf2c38b1..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroupList.tsx +++ /dev/null @@ -1,52 +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 React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { ErrorGroupListAPIResponse } from 'x-pack/plugins/apm/server/lib/errors/get_error_groups'; -import { loadErrorGroupList } from '../../services/rest/apm/error_groups'; -import { IReduxState } from '../rootReducer'; -import { IUrlParams } from '../urlParams'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'errorGroupList'; -const INITIAL_DATA: ErrorGroupListAPIResponse = []; -const withInitialData = createInitialDataSelector(INITIAL_DATA); - -export function getErrorGroupList(state: IReduxState) { - return withInitialData(state.reactReduxRequest[ID]); -} - -export function ErrorGroupOverviewRequest({ - urlParams, - render -}: { - urlParams: IUrlParams; - render: RRRRender; -}) { - const { - serviceName, - start, - end, - sortField, - sortDirection, - kuery - } = urlParams; - - if (!(serviceName && start && end)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/helpers.ts b/x-pack/plugins/apm/public/store/reactReduxRequest/helpers.ts deleted file mode 100644 index 7575120cfc45b..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/helpers.ts +++ /dev/null @@ -1,18 +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 { get } from 'lodash'; -import { createSelector } from 'reselect'; - -export function createInitialDataSelector(initialData: T) { - return createSelector( - state => state, - state => { - const data: T = get(state, 'data') || initialData; - return { ...state, data }; - } - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/license.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/license.tsx deleted file mode 100644 index a8bc527c50af1..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/license.tsx +++ /dev/null @@ -1,35 +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 React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { LicenseApiResponse, loadLicense } from '../../services/rest/xpack'; -import { IReduxState } from '../rootReducer'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'license'; -const INITIAL_DATA = { - features: { - watcher: { is_available: false }, - ml: { is_available: false } - }, - license: { is_active: false } -}; - -const withInitialData = createInitialDataSelector(INITIAL_DATA); - -export function getLicense(state: IReduxState) { - return withInitialData(state.reactReduxRequest[ID]); -} - -export function LicenceRequest({ - render -}: { - render: RRRRender; -}) { - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/machineLearningJobs.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/machineLearningJobs.tsx deleted file mode 100644 index 5fd06b3a56804..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/machineLearningJobs.tsx +++ /dev/null @@ -1,39 +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 React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { getMLJob, MLJobApiResponse } from '../../services/rest/ml'; -import { IReduxState } from '../rootReducer'; -import { createInitialDataSelector } from './helpers'; - -const INITIAL_DATA = { count: 0, jobs: [] }; -const withInitialData = createInitialDataSelector(INITIAL_DATA); -const ID = 'MLJobs'; - -function selectMlJobs(state: IReduxState) { - return withInitialData(state.reactReduxRequest[ID]); -} - -export function MLJobsRequest({ - serviceName, - transactionType = '*', - render -}: { - serviceName: string; - transactionType?: string; - render: RRRRender; -}) { - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/serviceDetails.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/serviceDetails.tsx deleted file mode 100644 index 274f620c7f933..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/serviceDetails.tsx +++ /dev/null @@ -1,51 +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 { first, get } from 'lodash'; -import React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams'; -import { ServiceAPIResponse } from 'x-pack/plugins/apm/server/lib/services/get_service'; -import { loadServiceDetails } from '../../services/rest/apm/services'; -import { IReduxState } from '../rootReducer'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'serviceDetails'; -const INITIAL_DATA = { types: [] }; -const withInitialData = createInitialDataSelector(INITIAL_DATA); - -export function getServiceDetails(state: IReduxState) { - return withInitialData(state.reactReduxRequest[ID]); -} - -export function getDefaultTransactionType(state: IReduxState) { - const types: string[] = get(state.reactReduxRequest[ID], 'data.types'); - return first(types); -} - -export function ServiceDetailsRequest({ - urlParams, - render -}: { - urlParams: IUrlParams; - render: RRRRender; -}) { - const { serviceName, start, end, kuery } = urlParams; - - if (!(serviceName && start && end)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/serviceList.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/serviceList.tsx deleted file mode 100644 index 22ea86e906502..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/serviceList.tsx +++ /dev/null @@ -1,49 +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 React from 'react'; -import { Request, RRRRender, RRRRenderResponse } from 'react-redux-request'; -import { ServiceListAPIResponse } from 'x-pack/plugins/apm/server/lib/services/get_services'; -import { loadServiceList } from '../../services/rest/apm/services'; -import { IReduxState } from '../rootReducer'; -import { IUrlParams } from '../urlParams'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'serviceList'; -const INITIAL_DATA: ServiceListAPIResponse = []; -const withInitialData = createInitialDataSelector( - INITIAL_DATA -); - -export function getServiceList( - state: IReduxState -): RRRRenderResponse { - return withInitialData(state.reactReduxRequest[ID]); -} - -export function ServiceListRequest({ - urlParams, - render -}: { - urlParams: IUrlParams; - render: RRRRender; -}) { - const { start, end, kuery } = urlParams; - - if (!(start && end)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/serviceMetricsCharts.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/serviceMetricsCharts.tsx deleted file mode 100644 index 19a0dbdc0327e..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/serviceMetricsCharts.tsx +++ /dev/null @@ -1,92 +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 React from 'react'; -import { Request, RRRRender, RRRRenderResponse } from 'react-redux-request'; -import { createSelector } from 'reselect'; -import { loadMetricsChartDataForService } from 'x-pack/plugins/apm/public/services/rest/apm/metrics'; -import { IMemoryChartData } from 'x-pack/plugins/apm/public/store/selectors/chartSelectors'; -import { MetricsChartAPIResponse } from 'x-pack/plugins/apm/server/lib/metrics/get_all_metrics_chart_data'; -import { IReduxState } from '../rootReducer'; -import { getCPUSeries, getMemorySeries } from '../selectors/chartSelectors'; -import { getUrlParams, IUrlParams } from '../urlParams'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'metricsChartData'; -const INITIAL_DATA: MetricsChartAPIResponse = { - memory: { - series: { - memoryUsedAvg: [], - memoryUsedMax: [] - }, - overallValues: { - memoryUsedAvg: null, - memoryUsedMax: null - }, - totalHits: 0 - }, - cpu: { - series: { - systemCPUAverage: [], - systemCPUMax: [], - processCPUAverage: [], - processCPUMax: [] - }, - overallValues: { - systemCPUAverage: null, - systemCPUMax: null, - processCPUAverage: null, - processCPUMax: null - }, - totalHits: 0 - } -}; - -type MetricsChartDataSelector = ( - state: IReduxState -) => RRRRenderResponse; - -const withInitialData = createInitialDataSelector( - INITIAL_DATA -); - -const selectMetricsChartData: MetricsChartDataSelector = state => - withInitialData(state.reactReduxRequest[ID]); - -export const selectTransformedMetricsChartData = createSelector( - [getUrlParams, selectMetricsChartData], - (urlParams, response) => ({ - ...response, - data: { - ...response.data, - memory: getMemorySeries(urlParams, response.data.memory), - cpu: getCPUSeries(response.data.cpu) - } - }) -); - -interface Props { - urlParams: IUrlParams; - render: RRRRender; -} - -export function MetricsChartDataRequest({ urlParams, render }: Props) { - const { serviceName, start, end } = urlParams; - - if (!(serviceName && start && end)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/traceList.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/traceList.tsx deleted file mode 100644 index 6bb98a9a1866a..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/traceList.tsx +++ /dev/null @@ -1,56 +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 React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { createSelector } from 'reselect'; -import { TraceListAPIResponse } from 'x-pack/plugins/apm/server/lib/traces/get_top_traces'; -import { loadTraceList } from '../../services/rest/apm/traces'; -import { IReduxState } from '../rootReducer'; -import { IUrlParams } from '../urlParams'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'traceList'; -const INITIAL_DATA: TraceListAPIResponse = []; -const withInitialData = createInitialDataSelector(INITIAL_DATA); - -const selectRRR = (state = {} as IReduxState) => state.reactReduxRequest; - -export const selectTraceList = createSelector( - [selectRRR], - reactReduxRequest => { - return withInitialData(reactReduxRequest[ID]); - } -); - -interface Props { - urlParams: IUrlParams; - render: RRRRender; -} - -export function TraceListRequest({ urlParams, render }: Props) { - const { start, end, kuery } = urlParams; - - if (!start || !end) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDetailsCharts.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDetailsCharts.tsx deleted file mode 100644 index 50b631d25ecfa..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDetailsCharts.tsx +++ /dev/null @@ -1,73 +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 React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { createSelector } from 'reselect'; -import { ITransactionChartData } from 'x-pack/plugins/apm/public/store/selectors/chartSelectors'; -import { TimeSeriesAPIResponse } from 'x-pack/plugins/apm/server/lib/transactions/charts'; -import { loadDetailsCharts } from '../../services/rest/apm/transaction_groups'; -import { IReduxState } from '../rootReducer'; -import { getTransactionCharts } from '../selectors/chartSelectors'; -import { getUrlParams, IUrlParams } from '../urlParams'; - -const ID = 'transactionDetailsCharts'; -const INITIAL_DATA: TimeSeriesAPIResponse = { - apmTimeseries: { - totalHits: 0, - responseTimes: { - avg: [], - p95: [], - p99: [] - }, - tpmBuckets: [], - overallAvgDuration: undefined - }, - anomalyTimeseries: undefined -}; - -export const getTransactionDetailsCharts = createSelector( - getUrlParams, - (state: IReduxState) => state.reactReduxRequest[ID], - (urlParams, detailCharts = {}) => { - return { - ...detailCharts, - data: getTransactionCharts(urlParams, detailCharts.data || INITIAL_DATA) - }; - } -); - -interface Props { - urlParams: IUrlParams; - render: RRRRender; -} - -export function TransactionDetailsChartsRequest({ urlParams, render }: Props) { - const { - serviceName, - start, - end, - transactionType, - transactionName, - kuery - } = urlParams; - - if (!(serviceName && start && end && transactionType && transactionName)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDistribution.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDistribution.tsx deleted file mode 100644 index b4232de6a9db2..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDistribution.tsx +++ /dev/null @@ -1,81 +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 React from 'react'; -import { Request, RRRRender, RRRRenderResponse } from 'react-redux-request'; -import { createSelector } from 'reselect'; -import { ITransactionDistributionAPIResponse } from 'x-pack/plugins/apm/server/lib/transactions/distribution'; -import { loadTransactionDistribution } from '../../services/rest/apm/transaction_groups'; -import { IReduxState } from '../rootReducer'; -import { IUrlParams } from '../urlParams'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'transactionDistribution'; -const INITIAL_DATA = { buckets: [], totalHits: 0, bucketSize: 0 }; -const withInitialData = createInitialDataSelector< - ITransactionDistributionAPIResponse ->(INITIAL_DATA); - -export function getTransactionDistribution( - state: IReduxState -): RRRRenderResponse { - return withInitialData(state.reactReduxRequest[ID]); -} - -export const getDefaultDistributionSample = createSelector( - getTransactionDistribution, - distribution => { - const { defaultSample = {} } = distribution.data; - return { - traceId: defaultSample.traceId, - transactionId: defaultSample.transactionId - }; - } -); - -export function TransactionDistributionRequest({ - urlParams, - render -}: { - urlParams: IUrlParams; - render: RRRRender; -}) { - const { - serviceName, - transactionType, - transactionId, - traceId, - start, - end, - transactionName, - kuery - } = urlParams; - - if (!(serviceName && transactionType && start && end && transactionName)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionList.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionList.tsx deleted file mode 100644 index 246af040be84b..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionList.tsx +++ /dev/null @@ -1,85 +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 React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { createSelector } from 'reselect'; -import { TransactionListAPIResponse } from 'x-pack/plugins/apm/server/lib/transactions/get_top_transactions'; -import { loadTransactionList } from '../../services/rest/apm/transaction_groups'; -import { IReduxState } from '../rootReducer'; -import { IUrlParams } from '../urlParams'; -import { createInitialDataSelector } from './helpers'; - -const ID = 'transactionList'; -const INITIAL_DATA: TransactionListAPIResponse = []; -const withInitialData = createInitialDataSelector( - INITIAL_DATA -); - -const getRelativeImpact = ( - impact: number, - impactMin: number, - impactMax: number -) => - Math.max( - ((impact - impactMin) / Math.max(impactMax - impactMin, 1)) * 100, - 1 - ); - -function getWithRelativeImpact(items: TransactionListAPIResponse) { - const impacts = items.map(({ impact }) => impact); - const impactMin = Math.min(...impacts); - const impactMax = Math.max(...impacts); - - return items.map(item => { - return { - ...item, - impactRelative: getRelativeImpact(item.impact, impactMin, impactMax) - }; - }); -} - -export const getTransactionList = createSelector( - (state: IReduxState) => withInitialData(state.reactReduxRequest[ID]), - transactionList => { - return { - ...transactionList, - data: getWithRelativeImpact(transactionList.data) - }; - } -); - -export function TransactionListRequest({ - urlParams, - render -}: { - urlParams: IUrlParams; - render: RRRRender; -}) { - const { serviceName, start, end, transactionType, kuery } = urlParams; - - if (!(serviceName && start && end)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionOverviewCharts.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionOverviewCharts.tsx deleted file mode 100644 index 520ba31e3229b..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionOverviewCharts.tsx +++ /dev/null @@ -1,97 +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 { get } from 'lodash'; -import React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { createSelector } from 'reselect'; -import { ITransactionChartData } from 'x-pack/plugins/apm/public/store/selectors/chartSelectors'; -import { TimeSeriesAPIResponse } from 'x-pack/plugins/apm/server/lib/transactions/charts'; -import { - loadOverviewCharts, - loadOverviewChartsForAllTypes -} from '../../services/rest/apm/transaction_groups'; -import { IReduxState } from '../rootReducer'; -import { getTransactionCharts } from '../selectors/chartSelectors'; -import { getUrlParams, IUrlParams } from '../urlParams'; - -const ID = 'transactionOverviewCharts'; -const INITIAL_DATA: TimeSeriesAPIResponse = { - apmTimeseries: { - totalHits: 0, - responseTimes: { - avg: [], - p95: [], - p99: [] - }, - tpmBuckets: [], - overallAvgDuration: undefined - }, - anomalyTimeseries: undefined -}; - -const selectChartData = (state: IReduxState) => state.reactReduxRequest[ID]; - -export const getTransactionOverviewCharts = createSelector( - [getUrlParams, selectChartData], - (urlParams, overviewCharts = {}) => { - return { - ...overviewCharts, - data: getTransactionCharts(urlParams, overviewCharts.data || INITIAL_DATA) - }; - } -); - -export const selectHasMLJob = createSelector( - [selectChartData], - chartData => get(chartData, 'data.anomalyTimeseries') !== undefined -); - -interface Props { - urlParams: IUrlParams; - render: RRRRender; -} - -export function TransactionOverviewChartsRequest({ urlParams, render }: Props) { - const { serviceName, start, end, transactionType, kuery } = urlParams; - - if (!(serviceName && start && end)) { - return null; - } - - return ( - - ); -} - -// Ignores transaction type from urlParams and requests charts -// for ALL transaction types within this service -export function TransactionOverviewChartsRequestForAllTypes({ - urlParams, - render -}: Props) { - const { serviceName, start, end, kuery } = urlParams; - - if (!(serviceName && start && end)) { - return null; - } - - return ( - - ); -} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/waterfall.tsx b/x-pack/plugins/apm/public/store/reactReduxRequest/waterfall.tsx deleted file mode 100644 index abd7e73702a3d..0000000000000 --- a/x-pack/plugins/apm/public/store/reactReduxRequest/waterfall.tsx +++ /dev/null @@ -1,51 +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 React from 'react'; -import { Request, RRRRender } from 'react-redux-request'; -import { TraceAPIResponse } from 'x-pack/plugins/apm/server/lib/traces/get_trace'; -import { - getWaterfall, - IWaterfall -} from '../../components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers'; -import { loadTrace } from '../../services/rest/apm/traces'; -import { IUrlParams } from '../urlParams'; - -export const ID = 'waterfall'; - -interface Props { - urlParams: IUrlParams; - traceId?: string; - render: RRRRender; -} - -export function WaterfallRequest({ urlParams, render, traceId }: Props) { - const { start, end } = urlParams; - - if (!(traceId && start && end)) { - return null; - } - - return ( - - id={ID} - fn={loadTrace} - args={[{ traceId, start, end }]} - render={({ - args, - data = { trace: [], errorsPerTransaction: {} }, - status - }) => { - const waterfall = getWaterfall( - data.trace, - data.errorsPerTransaction, - urlParams.transactionId - ); - return render({ args, data: waterfall, status }); - }} - /> - ); -} diff --git a/x-pack/plugins/apm/public/store/rootReducer.ts b/x-pack/plugins/apm/public/store/rootReducer.ts index 2395c3f0a6af2..0104e26d15416 100644 --- a/x-pack/plugins/apm/public/store/rootReducer.ts +++ b/x-pack/plugins/apm/public/store/rootReducer.ts @@ -5,20 +5,16 @@ */ import { Location } from 'history'; -import { reducer } from 'react-redux-request'; import { combineReducers } from 'redux'; -import { StringMap } from '../../typings/common'; import { locationReducer } from './location'; import { IUrlParams, urlParamsReducer } from './urlParams'; export interface IReduxState { location: Location; urlParams: IUrlParams; - reactReduxRequest: StringMap; } export const rootReducer = combineReducers({ location: locationReducer, - urlParams: urlParamsReducer, - reactReduxRequest: reducer + urlParams: urlParamsReducer }); diff --git a/x-pack/plugins/apm/public/store/selectors/chartSelectors.ts b/x-pack/plugins/apm/public/store/selectors/chartSelectors.ts index 424fe1515819f..7eedff75a1c28 100644 --- a/x-pack/plugins/apm/public/store/selectors/chartSelectors.ts +++ b/x-pack/plugins/apm/public/store/selectors/chartSelectors.ts @@ -65,13 +65,27 @@ export interface ITransactionChartData { noHits: boolean; tpmSeries: ITpmBucket[] | IEmptySeries[]; responseTimeSeries: TimeSerie[] | IEmptySeries[]; + hasMLJob: boolean; } +const INITIAL_DATA = { + apmTimeseries: { + totalHits: 0, + responseTimes: { + avg: [], + p95: [], + p99: [] + }, + tpmBuckets: [], + overallAvgDuration: undefined + }, + anomalyTimeseries: undefined +}; + export function getTransactionCharts( - urlParams: IUrlParams, - timeseriesResponse: TimeSeriesAPIResponse -) { - const { start, end, transactionType } = urlParams; + { start, end, transactionType }: IUrlParams, + timeseriesResponse: TimeSeriesAPIResponse = INITIAL_DATA +): ITransactionChartData { const { apmTimeseries, anomalyTimeseries } = timeseriesResponse; const noHits = apmTimeseries.totalHits === 0; const tpmSeries = noHits @@ -82,26 +96,22 @@ export function getTransactionCharts( ? getEmptySerie(start, end) : getResponseTimeSeries(apmTimeseries, anomalyTimeseries); - const chartsResult: ITransactionChartData = { + return { noHits, tpmSeries, - responseTimeSeries + responseTimeSeries, + hasMLJob: timeseriesResponse.anomalyTimeseries !== undefined }; - - return chartsResult; } -export interface IMemoryChartData extends MetricsChartAPIResponse { - series: TimeSerie[] | IEmptySeries[]; -} +export type MemoryMetricSeries = ReturnType; export function getMemorySeries( - urlParams: IUrlParams, + { start, end }: IUrlParams, memoryChartResponse: MetricsChartAPIResponse['memory'] ) { - const { start, end } = urlParams; const { series, overallValues, totalHits } = memoryChartResponse; - const seriesList: IMemoryChartData['series'] = + const seriesList = totalHits === 0 ? getEmptySerie(start, end) : [ @@ -132,14 +142,12 @@ export function getMemorySeries( ]; return { - ...memoryChartResponse, + totalHits: memoryChartResponse.totalHits, series: seriesList }; } -export interface ICPUChartData extends MetricsChartAPIResponse { - series: TimeSerie[]; -} +export type CPUMetricSeries = ReturnType; export function getCPUSeries(CPUChartResponse: MetricsChartAPIResponse['cpu']) { const { series, overallValues } = CPUChartResponse; @@ -183,7 +191,7 @@ export function getCPUSeries(CPUChartResponse: MetricsChartAPIResponse['cpu']) { } ]; - return { ...CPUChartResponse, series: seriesList }; + return { totalHits: CPUChartResponse.totalHits, series: seriesList }; } interface TimeSerie { diff --git a/x-pack/plugins/apm/public/store/selectors/license.ts b/x-pack/plugins/apm/public/store/selectors/license.ts deleted file mode 100644 index 24ce0a4953b93..0000000000000 --- a/x-pack/plugins/apm/public/store/selectors/license.ts +++ /dev/null @@ -1,17 +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 { createSelector } from 'reselect'; -import { getLicense } from 'x-pack/plugins/apm/public/store/reactReduxRequest/license'; - -export const selectIsMLAvailable = createSelector( - [getLicense], - license => - license.data && - license.data.features && - license.data.features.ml && - license.data.features.ml.is_available -); diff --git a/x-pack/plugins/apm/public/store/urlParams.ts b/x-pack/plugins/apm/public/store/urlParams.ts index 270f3c690624b..c9bfeef2ee638 100644 --- a/x-pack/plugins/apm/public/store/urlParams.ts +++ b/x-pack/plugins/apm/public/store/urlParams.ts @@ -7,14 +7,11 @@ import datemath from '@elastic/datemath'; import { Location } from 'history'; import { compact, pick } from 'lodash'; -import { createSelector } from 'reselect'; import { legacyDecodeURIComponent, toQuery } from '../components/shared/Links/url_helpers'; import { LOCATION_UPDATE } from './location'; -import { getDefaultTransactionType } from './reactReduxRequest/serviceDetails'; -import { getDefaultDistributionSample } from './reactReduxRequest/transactionDistribution'; import { IReduxState } from './rootReducer'; // ACTION TYPES @@ -153,16 +150,11 @@ export function toNumber(value?: string) { } } -function toString(str?: string | string[]) { - if ( - str === '' || - str === 'null' || - str === 'undefined' || - Array.isArray(str) - ) { +function toString(value?: string) { + if (value === '' || value === 'null' || value === 'undefined') { return; } - return str; + return value; } export function toBoolean(value?: string) { @@ -211,23 +203,9 @@ export function refreshTimeRange(time: TimeRange): TimeRangeRefreshAction { } // Selectors -export const getUrlParams = createSelector( - (state: IReduxState) => state.urlParams, - getDefaultTransactionType, - getDefaultDistributionSample, - ( - urlParams, - transactionType: string, - { traceId, transactionId } - ): IUrlParams => { - return { - transactionType, - transactionId, - traceId, - ...urlParams - }; - } -); +export function getUrlParams(state: IReduxState) { + return state.urlParams; +} export interface IUrlParams { detailTab?: string; diff --git a/x-pack/plugins/apm/public/utils/testHelpers.tsx b/x-pack/plugins/apm/public/utils/testHelpers.tsx index 845dc7b19dd14..3b720cba6e03d 100644 --- a/x-pack/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/plugins/apm/public/utils/testHelpers.tsx @@ -8,11 +8,9 @@ import { mount, ReactWrapper } from 'enzyme'; import enzymeToJson from 'enzyme-to-json'; -import createHistory from 'history/createHashHistory'; import 'jest-styled-components'; import moment from 'moment'; import { Moment } from 'moment-timezone'; -import PropTypes from 'prop-types'; import React from 'react'; import { Provider } from 'react-redux'; import { MemoryRouter } from 'react-router-dom'; @@ -29,51 +27,6 @@ export function toJson(wrapper: ReactWrapper) { }); } -const defaultRoute = { - match: { path: '/', url: '/', params: {}, isExact: true }, - location: { pathname: '/', search: '', hash: '', key: '4yyjf5' } -}; - -export function mountWithRouterAndStore( - Component: React.ReactElement, - storeState = {}, - route = defaultRoute -) { - const store = createMockStore(storeState); - const history = createHistory(); - - const options = { - context: { - store, - router: { - history, - route - } - }, - childContextTypes: { - store: PropTypes.object.isRequired, - router: PropTypes.object.isRequired - } - }; - - return mount(Component, options); -} - -export function mountWithStore(Component: React.ReactElement, storeState = {}) { - const store = createMockStore(storeState); - - const options = { - context: { - store - }, - childContextTypes: { - store: PropTypes.object.isRequired - } - }; - - return mount(Component, options); -} - export function mockMoment() { // avoid timezone issues jest @@ -90,11 +43,6 @@ export function mockMoment() { }); } -// Await this when you need to "flush" promises to immediately resolve or throw in tests -export async function asyncFlush() { - return new Promise(resolve => setTimeout(resolve, 0)); -} - // Useful for getting the rendered href from any kind of link component export async function getRenderedHref( Component: React.FunctionComponent<{}>, @@ -109,7 +57,7 @@ export async function getRenderedHref( ); - await asyncFlush(); + await tick(); return mounted.render().attr('href'); } @@ -118,3 +66,10 @@ export function mockNow(date: string) { const fakeNow = new Date(date).getTime(); return jest.spyOn(Date, 'now').mockReturnValue(fakeNow); } + +export function delay(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +// Await this when you need to "flush" promises to immediately resolve or throw in tests +export const tick = () => new Promise(resolve => setImmediate(resolve, 0)); diff --git a/x-pack/plugins/apm/typings/react-redux-request.d.ts b/x-pack/plugins/apm/typings/react-redux-request.d.ts deleted file mode 100644 index de49e9dc648a5..0000000000000 --- a/x-pack/plugins/apm/typings/react-redux-request.d.ts +++ /dev/null @@ -1,36 +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. - */ - -// Everything in here should be moved to http://github.com/sqren/react-redux-request - -declare module 'react-redux-request' { - import React from 'react'; - - // status and args are optional, especially for places that use initial data in a reducer - export interface RRRRenderResponse { - status?: 'SUCCESS' | 'LOADING' | 'FAILURE'; - data: T; - args?: P; - } - - export type RRRRender = ( - res: RRRRenderResponse - ) => React.ReactNode; - - export interface RequestProps { - id: string; - fn: (args: any) => Promise; - selector?: (state: any) => any; - args?: any[]; - render?: RRRRender; - } - - export function reducer(state: any): any; - - export class Request extends React.Component< - RequestProps - > {} -} diff --git a/yarn.lock b/yarn.lock index a09253ff177c7..4bd503343a588 100644 --- a/yarn.lock +++ b/yarn.lock @@ -772,13 +772,20 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.3.4": +"@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" integrity sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g== dependencies: regenerator-runtime "^0.12.0" +"@babel/runtime@^7.4.2": + version "7.4.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.2.tgz#f5ab6897320f16decd855eed70b705908a313fe8" + integrity sha512-7Bl2rALb7HpvXFL7TETNzKSAeBVCPHELzc0C//9FCxN8nsiueWSJBqaF+2oIJScyILStASR/Cx5WMkXGYTiJFA== + dependencies: + regenerator-runtime "^0.13.2" + "@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" @@ -1057,6 +1064,14 @@ normalize-path "^2.0.1" through2 "^2.0.3" +"@jest/types@^24.5.0": + version "24.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.5.0.tgz#feee214a4d0167b0ca447284e95a57aa10b3ee95" + integrity sha512-kN7RFzNMf2R8UDadPOl6ReyI+MT8xfqRuAnuVL+i4gwjv/zubdDK+EDeLHYwq1j0CSSR2W/MmgaRlMZJzXdmVA== + dependencies: + "@types/istanbul-lib-coverage" "^1.1.0" + "@types/yargs" "^12.0.9" + "@mapbox/geojson-area@0.2.2": version "0.2.2" resolved "https://registry.yarnpkg.com/@mapbox/geojson-area/-/geojson-area-0.2.2.tgz#18d7814aa36bf23fbbcc379f8e26a22927debf10" @@ -1143,6 +1158,11 @@ dependencies: url-pattern "^1.0.3" +"@sheerun/mutationobserver-shim@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b" + integrity sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q== + "@sindresorhus/is@^0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" @@ -1946,6 +1966,11 @@ dependencies: "@types/node" "*" +"@types/istanbul-lib-coverage@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#2cc2ca41051498382b43157c8227fea60363f94a" + integrity sha512-ohkhb9LehJy+PA40rDtGAji61NCgdtKLAlFoYp4cnuuQEswwdK3vz9SOIkkyc3wrk8dzjphQApNs56yyXLStaQ== + "@types/jest-diff@*": version "20.0.1" resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89" @@ -2046,6 +2071,11 @@ resolved "https://registry.yarnpkg.com/@types/loglevel/-/loglevel-1.5.3.tgz#adfce55383edc5998a2170ad581b3e23d6adb5b8" integrity sha512-TzzIZihV+y9kxSg5xJMkyIkaoGkXi50isZTtGHObNHRqAAwjGNjSCNPI7AUAv0tZUKTq9f2cdkCUd/2JVZUTrA== +"@types/lru-cache@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.0.tgz#57f228f2b80c046b4a1bd5cac031f81f207f4f03" + integrity sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w== + "@types/mime-db@*": version "1.27.0" resolved "https://registry.yarnpkg.com/@types/mime-db/-/mime-db-1.27.0.tgz#9bc014a1fd1fdf47649c1a54c6dd7966b8284792" @@ -2114,6 +2144,11 @@ resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.25.tgz#b6f55062827a4787fe4ab151cf3412a468e65271" integrity sha512-ShHzHkYD+Ldw3eyttptCpUhF1/mkInWwasQkCNXZHOsJMJ/UMa8wXrxSrTJaVk0r4pLK/VnESVM0wFsfQzNEKQ== +"@types/object-hash@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/object-hash/-/object-hash-1.2.0.tgz#d65904331bd0b05c7d5ece75f9ddfdbe82affd30" + integrity sha512-0JKYQRatHdzijO/ni7JV5eHUJWaMRpGvwiABk8U5iAk5Corm0yLNEfYGNkZWYc+wCyCKKpg0+TsZIvP8AymIYA== + "@types/opn@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/opn/-/opn-5.1.0.tgz#bff7bc371677f4bdbb37884400e03fd81f743927" @@ -2421,6 +2456,11 @@ "@types/events" "*" "@types/node" "*" +"@types/yargs@^12.0.9": + version "12.0.10" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.10.tgz#17a8ec65cd8e88f51b418ceb271af18d3137df67" + integrity sha512-WsVzTPshvCSbHThUduGGxbmnwcpkgSctHGHTqzWyFg4lYAuV5qXlyFPOsP3OWqCINfmg/8VXP+zJaa4OxEsBQQ== + "@types/zen-observable@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" @@ -7686,6 +7726,26 @@ dom-serializer@0, dom-serializer@~0.1.0: domelementtype "^1.3.0" entities "^1.1.1" +dom-testing-library@^3.13.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/dom-testing-library/-/dom-testing-library-3.17.1.tgz#3291bc3cf68c555ba5e663697ee77d604aaa122b" + integrity sha512-SbkaRfQvuLjnv+xFgSo/cmKoN9tjBL6Rh1f3nQH9jnjUe5q+keRwacYSi3uSpcB4D1K768iavCayKH3ZN9ea+g== + dependencies: + "@babel/runtime" "^7.3.4" + "@sheerun/mutationobserver-shim" "^0.3.2" + pretty-format "^24.0.0" + wait-for-expect "^1.1.0" + +dom-testing-library@^3.18.2: + version "3.18.2" + resolved "https://registry.yarnpkg.com/dom-testing-library/-/dom-testing-library-3.18.2.tgz#07d65166743ad3299b7bee5b488e9622c31241bc" + integrity sha512-+nYUgGhHarrCY8kLVmyHlgM+IGwBXXrYsWIJB6vpAx2ne9WFgKfwMGcOkkTKQhuAro0sP6RIuRGfm5NF3+ccmQ== + dependencies: + "@babel/runtime" "^7.3.4" + "@sheerun/mutationobserver-shim" "^0.3.2" + pretty-format "^24.5.0" + wait-for-expect "^1.1.0" + dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" @@ -16389,6 +16449,11 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-hash@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" + integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== + object-inspect@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" @@ -17672,6 +17737,16 @@ pretty-format@^24.0.0: ansi-regex "^4.0.0" ansi-styles "^3.2.0" +pretty-format@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.5.0.tgz#cc69a0281a62cd7242633fc135d6930cd889822d" + integrity sha512-/3RuSghukCf8Riu5Ncve0iI+BzVkbRU5EeUoArKARZobREycuH5O4waxvaNIloEXdb0qwgmEAed5vTpX1HNROQ== + dependencies: + "@jest/types" "^24.5.0" + ansi-regex "^4.0.0" + ansi-styles "^3.2.0" + react-is "^16.8.4" + pretty-hrtime@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" @@ -18483,6 +18558,14 @@ react-grid-layout@^0.16.2: react-draggable "3.x" react-resizable "1.x" +react-hooks-testing-library@^0.3.8: + version "0.3.8" + resolved "https://registry.yarnpkg.com/react-hooks-testing-library/-/react-hooks-testing-library-0.3.8.tgz#717595ed7be500023963dd502f188aa932bf70f0" + integrity sha512-YFnyd2jH2voikSBGufqhprnxMTHgosOHlO5EXhuQycWxfeTCIiw/17aiYbpvRRDRB/0j8QvI/jHXMNVBKw7WzA== + dependencies: + "@babel/runtime" "^7.4.2" + react-testing-library "^6.0.2" + react-input-autosize@^2.1.2, react-input-autosize@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8" @@ -18524,6 +18607,11 @@ react-is@^16.8.1, react-is@^16.8.2: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.2.tgz#09891d324cad1cb0c1f2d91f70a71a4bee34df0f" integrity sha512-D+NxhSR2HUCjYky1q1DwpNUD44cDpUXzSmmFyC3ug1bClcU/iDNy0YNn1iwme28fn+NFhpA13IndOd42CrFb+Q== +react-is@^16.8.4: + version "16.8.5" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.5.tgz#c54ac229dd66b5afe0de5acbe47647c3da692ff8" + integrity sha512-sudt2uq5P/2TznPV4Wtdi+Lnq3yaYW8LfvPKLM9BKD8jJNBkxMVyB0C9/GmVhLw7Jbdmndk/73n7XQGeN9A3QQ== + react-is@~16.3.0: version "16.3.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.3.2.tgz#f4d3d0e2f5fbb6ac46450641eb2e25bf05d36b22" @@ -18770,6 +18858,22 @@ react-test-renderer@^16.0.0-0, react-test-renderer@^16.8.0: react-is "^16.8.2" scheduler "^0.13.2" +react-testing-library@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-6.0.0.tgz#81edfcfae8a795525f48685be9bf561df45bb35d" + integrity sha512-h0h+YLe4KWptK6HxOMnoNN4ngu3W8isrwDmHjPC5gxc+nOZOCurOvbKVYCvvuAw91jdO7VZSm/5KR7TxKnz0qA== + dependencies: + "@babel/runtime" "^7.3.1" + dom-testing-library "^3.13.1" + +react-testing-library@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-6.0.3.tgz#8b5d276a353c17ce4f7486015bb7a1c8827c442c" + integrity sha512-tN0A6nywSOoL8kriqru3rSdw31PxuquL7xnW6xBI0aTNw0VO3kZQtaEa0npUH9dX0MIsSunB0nbElRrc4VtAzw== + dependencies: + "@babel/runtime" "^7.4.2" + dom-testing-library "^3.18.2" + react-textarea-autosize@^7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-7.0.4.tgz#4e4be649b544a88713e7b5043f76950f35d3d503" @@ -19238,6 +19342,11 @@ regenerator-runtime@^0.12.0, regenerator-runtime@^0.12.1: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== +regenerator-runtime@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447" + integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA== + regenerator-transform@^0.13.3: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb" @@ -23911,6 +24020,11 @@ w3c-hr-time@^1.0.1: dependencies: browser-process-hrtime "^0.1.2" +wait-for-expect@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.1.0.tgz#6607375c3f79d32add35cd2c87ce13f351a3d453" + integrity sha512-vQDokqxyMyknfX3luCDn16bSaRcOyH6gGuUXMIbxBLeTo6nWuEWYqMTT9a+44FmW8c2m6TRWBdNvBBjA1hwEKg== + walk@2.3.x: version "2.3.9" resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.9.tgz#31b4db6678f2ae01c39ea9fb8725a9031e558a7b" From 7e43afaad0a8f177b182cb686d11867d97007a57 Mon Sep 17 00:00:00 2001 From: Philipp B Date: Thu, 28 Mar 2019 17:59:19 +0300 Subject: [PATCH 83/96] (Accessibility) "Add" buttons provide no context on Sample Data page. (#33769) * aria described by for sample button --- .../__snapshots__/add_data.test.js.snap | 126 ++++++++++++++++-- .../kibana/public/home/components/add_data.js | 88 +++++++----- 2 files changed, 164 insertions(+), 50 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap index 4daa4eeebf4ab..ce99cbbf5408f 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap @@ -47,9 +47,16 @@ exports[`apmUiEnabled 1`] = ` > + APM automatically collects in-depth performance metrics and errors from inside your applications. + + } footer={ + Ingest logs from popular data sources and easily visualize in preconfigured dashboards. + + } footer={ + Collect metrics from the operating system and services running on your servers. + + } footer={ + Centralize security events for interactive investigation in ready-to-go visualizations. + + } footer={ + Ingest logs from popular data sources and easily visualize in preconfigured dashboards. + + } footer={ + Collect metrics from the operating system and services running on your servers. + + } footer={ + Centralize security events for interactive investigation in ready-to-go visualizations. + + } footer={ + APM automatically collects in-depth performance metrics and errors from inside your applications. + + } footer={ + Ingest logs from popular data sources and easily visualize in preconfigured dashboards. + + } footer={ + Collect metrics from the operating system and services running on your servers. + + } footer={ + Centralize security events for interactive investigation in ready-to-go visualizations. + + } footer={ + Ingest logs from popular data sources and easily visualize in preconfigured dashboards. + + } footer={ + Collect metrics from the operating system and services running on your servers. + + } footer={ + Centralize security events for interactive investigation in ready-to-go visualizations. + + } footer={ { const renderCards = () => { - const apmTitle = intl.formatMessage({ - id: 'kbn.home.addData.apm.nameTitle', defaultMessage: 'APM' - }); - const apmDescription = intl.formatMessage({ - id: 'kbn.home.addData.apm.nameDescription', - defaultMessage: 'APM automatically collects in-depth performance metrics and errors from inside your applications.' - }); - const loggingTitle = intl.formatMessage({ - id: 'kbn.home.addData.logging.nameTitle', defaultMessage: 'Logging' - }); - const loggingDescription = intl.formatMessage({ - id: 'kbn.home.addData.logging.nameDescription', - defaultMessage: 'Ingest logs from popular data sources and easily visualize in preconfigured dashboards.' - }); - const metricsTitle = intl.formatMessage({ - id: 'kbn.home.addData.metrics.nameTitle', defaultMessage: 'Metrics' - }); - const metricsDescription = intl.formatMessage({ - id: 'kbn.home.addData.metrics.nameDescription', - defaultMessage: 'Collect metrics from the operating system and services running on your servers.' - }); - const securityTitle = intl.formatMessage({ - id: 'kbn.home.addData.security.nameTitle', defaultMessage: 'Security analytics' - }); - const securityDescription = intl.formatMessage({ - id: 'kbn.home.addData.security.nameDescription', - defaultMessage: 'Centralize security events for interactive investigation in ready-to-go visualizations.' - }); + const ampData = { + title: intl.formatMessage({ + id: 'kbn.home.addData.apm.nameTitle', defaultMessage: 'APM' + }), + description: intl.formatMessage({ + id: 'kbn.home.addData.apm.nameDescription', + defaultMessage: 'APM automatically collects in-depth performance metrics and errors from inside your applications.' + }), + ariaDescribedby: 'aria-describedby.addAmpButtonLabel' + }; + const loggingData = { + title: intl.formatMessage({ + id: 'kbn.home.addData.logging.nameTitle', defaultMessage: 'Logging' + }), + description: intl.formatMessage({ + id: 'kbn.home.addData.logging.nameDescription', + defaultMessage: 'Ingest logs from popular data sources and easily visualize in preconfigured dashboards.' + }), + ariaDescribedby: 'aria-describedby.addLogDataButtonLabel' + }; + const metricsData = { + title: intl.formatMessage({ + id: 'kbn.home.addData.metrics.nameTitle', defaultMessage: 'Metrics' + }), + description: intl.formatMessage({ + id: 'kbn.home.addData.metrics.nameDescription', + defaultMessage: 'Collect metrics from the operating system and services running on your servers.' + }), + ariaDescribedby: 'aria-describedby.addMetricsButtonLabel' + }; + const securityData = { + title: intl.formatMessage({ + id: 'kbn.home.addData.security.nameTitle', defaultMessage: 'Security analytics' + }), + description: intl.formatMessage({ + id: 'kbn.home.addData.security.nameDescription', + defaultMessage: 'Centralize security events for interactive investigation in ready-to-go visualizations.' + }), + ariaDescribedby: 'aria-describedby.addSecurityButtonLabel' + }; const getApmCard = () => ( } - title={apmTitle} - description={apmDescription} + title={ampData.title} + description={{ampData.description}} footer={ { } - title={loggingTitle} - description={loggingDescription} + title={loggingData.title} + description={{loggingData.description}} footer={ { } - title={metricsTitle} - description={metricsDescription} + title={metricsData.title} + description={{metricsData.description}} footer={ { } - title={securityTitle} - description={securityDescription} + title={securityData.title} + description={{securityData.description}} footer={ Date: Thu, 28 Mar 2019 17:22:44 +0100 Subject: [PATCH 84/96] Typesciptify Basic Authentication provider and move its tests to Jest. (#34045) --- .../lib/__tests__/__fixtures__/request.ts | 2 +- .../{__tests__/basic.js => basic.test.ts} | 168 +++++++++-------- .../providers/{basic.js => basic.ts} | 170 +++++++++--------- 3 files changed, 173 insertions(+), 167 deletions(-) rename x-pack/plugins/security/server/lib/authentication/providers/{__tests__/basic.js => basic.test.ts} (56%) rename x-pack/plugins/security/server/lib/authentication/providers/{basic.js => basic.ts} (53%) diff --git a/x-pack/plugins/security/server/lib/__tests__/__fixtures__/request.ts b/x-pack/plugins/security/server/lib/__tests__/__fixtures__/request.ts index b074cfe0f0307..061c8fdad17e3 100644 --- a/x-pack/plugins/security/server/lib/__tests__/__fixtures__/request.ts +++ b/x-pack/plugins/security/server/lib/__tests__/__fixtures__/request.ts @@ -39,5 +39,5 @@ export function requestFixture({ query: search ? url.parse(search, true /* parseQueryString */).query : {}, payload, state: { user: 'these are the contents of the user client cookie' }, - } as any) as Request; + } as any) as Request & { loginAttempt: () => LoginAttempt; getBasePath: () => string }; } diff --git a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js b/x-pack/plugins/security/server/lib/authentication/providers/basic.test.ts similarity index 56% rename from x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js rename to x-pack/plugins/security/server/lib/authentication/providers/basic.test.ts index eaaa6fae4df3c..ebe984e41a2c5 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js +++ b/x-pack/plugins/security/server/lib/authentication/providers/basic.test.ts @@ -4,30 +4,31 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; import sinon from 'sinon'; -import { requestFixture } from '../../../__tests__/__fixtures__/request'; -import { LoginAttempt } from '../../login_attempt'; -import { BasicAuthenticationProvider, BasicCredentials } from '../basic'; +import { requestFixture } from '../../__tests__/__fixtures__/request'; +import { LoginAttempt } from '../login_attempt'; +import { BasicAuthenticationProvider, BasicCredentials } from './basic'; -function generateAuthorizationHeader(username, password) { - const { headers: { authorization } } = BasicCredentials.decorateRequest( - requestFixture(), username, password - ); +function generateAuthorizationHeader(username: string, password: string) { + const { + headers: { authorization }, + } = BasicCredentials.decorateRequest(requestFixture(), username, password); return authorization; } describe('BasicAuthenticationProvider', () => { describe('`authenticate` method', () => { - let provider; - let callWithRequest; + let provider: BasicAuthenticationProvider; + let callWithRequest: sinon.SinonStub; beforeEach(() => { callWithRequest = sinon.stub(); provider = new BasicAuthenticationProvider({ - client: { callWithRequest }, - log() {}, - basePath: '/base-path' + client: { callWithRequest } as any, + log() { + // no-op + }, + basePath: '/base-path', }); }); @@ -39,30 +40,28 @@ describe('BasicAuthenticationProvider', () => { null ); - expect(authenticationResult.notHandled()).to.be(true); + expect(authenticationResult.notHandled()).toBe(true); }); it('redirects non-AJAX requests that can not be authenticated to the login page.', async () => { const authenticationResult = await provider.authenticate( - requestFixture({ path: '/some-path # that needs to be encoded', basePath: '/s/foo' }), + requestFixture({ + path: '/some-path # that needs to be encoded', + basePath: '/s/foo', + }), null ); - expect(authenticationResult.redirected()).to.be(true); - expect(authenticationResult.redirectURL).to.be( + expect(authenticationResult.redirected()).toBe(true); + expect(authenticationResult.redirectURL).toBe( '/base-path/login?next=%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded' ); }); - it('does not handle authentication if state exists, but authorization property is missing.', - async () => { - const authenticationResult = await provider.authenticate( - requestFixture(), - {} - ); - - expect(authenticationResult.notHandled()).to.be(true); - }); + it('does not handle authentication if state exists, but authorization property is missing.', async () => { + const authenticationResult = await provider.authenticate(requestFixture(), {}); + expect(authenticationResult.notHandled()).toBe(true); + }); it('succeeds with valid login attempt and stores in session', async () => { const user = { username: 'user' }; @@ -70,17 +69,15 @@ describe('BasicAuthenticationProvider', () => { const request = requestFixture(); const loginAttempt = new LoginAttempt(); loginAttempt.setCredentials('user', 'password'); - request.loginAttempt.returns(loginAttempt); + (request.loginAttempt as sinon.SinonStub).returns(loginAttempt); - callWithRequest - .withArgs(request, 'shield.authenticate') - .returns(Promise.resolve(user)); + callWithRequest.withArgs(request, 'shield.authenticate').resolves(user); const authenticationResult = await provider.authenticate(request); - expect(authenticationResult.succeeded()).to.be(true); - expect(authenticationResult.user).to.be.eql(user); - expect(authenticationResult.state).to.be.eql({ authorization }); + expect(authenticationResult.succeeded()).toBe(true); + expect(authenticationResult.user).toEqual(user); + expect(authenticationResult.state).toEqual({ authorization }); sinon.assert.calledOnce(callWithRequest); }); @@ -88,14 +85,12 @@ describe('BasicAuthenticationProvider', () => { const request = BasicCredentials.decorateRequest(requestFixture(), 'user', 'password'); const user = { username: 'user' }; - callWithRequest - .withArgs(request, 'shield.authenticate') - .returns(Promise.resolve(user)); + callWithRequest.withArgs(request, 'shield.authenticate').resolves(user); const authenticationResult = await provider.authenticate(request); - expect(authenticationResult.succeeded()).to.be(true); - expect(authenticationResult.user).to.be.eql(user); + expect(authenticationResult.succeeded()).toBe(true); + expect(authenticationResult.user).toEqual(user); sinon.assert.calledOnce(callWithRequest); }); @@ -103,13 +98,13 @@ describe('BasicAuthenticationProvider', () => { const request = BasicCredentials.decorateRequest(requestFixture(), 'user', 'password'); const user = { username: 'user' }; - callWithRequest - .withArgs(request, 'shield.authenticate') - .returns(Promise.resolve(user)); + callWithRequest.withArgs(request, 'shield.authenticate').resolves(user); const authenticationResult = await provider.authenticate(request); - expect(authenticationResult.state).not.to.eql({ authorization: request.headers.authorization }); + expect(authenticationResult.state).not.toEqual({ + authorization: request.headers.authorization, + }); }); it('succeeds if only state is available.', async () => { @@ -119,13 +114,13 @@ describe('BasicAuthenticationProvider', () => { callWithRequest .withArgs(sinon.match({ headers: { authorization } }), 'shield.authenticate') - .returns(Promise.resolve(user)); + .resolves(user); const authenticationResult = await provider.authenticate(request, { authorization }); - expect(authenticationResult.succeeded()).to.be(true); - expect(authenticationResult.user).to.be.eql(user); - expect(authenticationResult.state).to.be.eql(undefined); + expect(authenticationResult.succeeded()).toBe(true); + expect(authenticationResult.user).toEqual(user); + expect(authenticationResult.state).toBeUndefined(); sinon.assert.calledOnce(callWithRequest); }); @@ -136,8 +131,8 @@ describe('BasicAuthenticationProvider', () => { const authenticationResult = await provider.authenticate(request, { authorization }); sinon.assert.notCalled(callWithRequest); - expect(request.headers.authorization).to.be('Bearer ***'); - expect(authenticationResult.notHandled()).to.be(true); + expect(request.headers.authorization).toBe('Bearer ***'); + expect(authenticationResult.notHandled()).toBe(true); }); it('fails if state contains invalid credentials.', async () => { @@ -147,15 +142,15 @@ describe('BasicAuthenticationProvider', () => { const authenticationError = new Error('Forbidden'); callWithRequest .withArgs(sinon.match({ headers: { authorization } }), 'shield.authenticate') - .returns(Promise.reject(authenticationError)); + .rejects(authenticationError); const authenticationResult = await provider.authenticate(request, { authorization }); - expect(request.headers).to.not.have.property('authorization'); - expect(authenticationResult.failed()).to.be(true); - expect(authenticationResult.user).to.be.eql(undefined); - expect(authenticationResult.state).to.be.eql(undefined); - expect(authenticationResult.error).to.be.eql(authenticationError); + expect(request.headers).not.toHaveProperty('authorization'); + expect(authenticationResult.failed()).toBe(true); + expect(authenticationResult.user).toBeUndefined(); + expect(authenticationResult.state).toBeUndefined(); + expect(authenticationResult.error).toBe(authenticationError); sinon.assert.calledOnce(callWithRequest); }); @@ -165,55 +160,68 @@ describe('BasicAuthenticationProvider', () => { const authorization = generateAuthorizationHeader('user1', 'password2'); // GetUser will be called with request's `authorization` header. - callWithRequest.withArgs(request, 'shield.authenticate').returns(Promise.resolve(user)); + callWithRequest.withArgs(request, 'shield.authenticate').resolves(user); const authenticationResult = await provider.authenticate(request, { authorization }); - expect(authenticationResult.succeeded()).to.be(true); - expect(authenticationResult.user).to.be.eql(user); - expect(authenticationResult.state).not.to.eql({ authorization: request.headers.authorization }); + expect(authenticationResult.succeeded()).toBe(true); + expect(authenticationResult.user).toEqual(user); + expect(authenticationResult.state).not.toEqual({ + authorization: request.headers.authorization, + }); sinon.assert.calledOnce(callWithRequest); }); }); describe('`deauthenticate` method', () => { - let provider; + let provider: BasicAuthenticationProvider; beforeEach(() => { provider = new BasicAuthenticationProvider({ - client: { callWithRequest: sinon.stub() }, - basePath: '/base-path' + client: { callWithRequest: sinon.stub() } as any, + log() { + // no-op + }, + basePath: '/base-path', }); }); it('always redirects to the login page.', async () => { const request = requestFixture(); const deauthenticateResult = await provider.deauthenticate(request); - expect(deauthenticateResult.redirected()).to.be(true); - expect(deauthenticateResult.redirectURL).to.be('/base-path/login'); + expect(deauthenticateResult.redirected()).toBe(true); + expect(deauthenticateResult.redirectURL).toBe('/base-path/login'); }); it('passes query string parameters to the login page.', async () => { const request = requestFixture({ search: '?next=%2Fapp%2Fml&msg=SESSION_EXPIRED' }); const deauthenticateResult = await provider.deauthenticate(request); - expect(deauthenticateResult.redirected()).to.be(true); - expect(deauthenticateResult.redirectURL).to.be('/base-path/login?next=%2Fapp%2Fml&msg=SESSION_EXPIRED'); + expect(deauthenticateResult.redirected()).toBe(true); + expect(deauthenticateResult.redirectURL).toBe( + '/base-path/login?next=%2Fapp%2Fml&msg=SESSION_EXPIRED' + ); }); }); describe('BasicCredentials', () => { it('`decorateRequest` fails if username or password is not provided.', () => { - expect(() => BasicCredentials.decorateRequest()).to - .throwError(/Request should be a valid object/); - expect(() => BasicCredentials.decorateRequest({})).to - .throwError(/Username should be a valid non-empty string/); - expect(() => BasicCredentials.decorateRequest({}, '')).to - .throwError(/Username should be a valid non-empty string/); - expect(() => BasicCredentials.decorateRequest({}, '', '')).to - .throwError(/Username should be a valid non-empty string/); - expect(() => BasicCredentials.decorateRequest({}, 'username', '')).to - .throwError(/Password should be a valid non-empty string/); - expect(() => BasicCredentials.decorateRequest({}, '', 'password')).to - .throwError(/Username should be a valid non-empty string/); + expect(() => + BasicCredentials.decorateRequest(undefined as any, undefined as any, undefined as any) + ).toThrowError('Request should be a valid object'); + expect(() => + BasicCredentials.decorateRequest({} as any, undefined as any, undefined as any) + ).toThrowError('Username should be a valid non-empty string'); + expect(() => BasicCredentials.decorateRequest({} as any, '', undefined as any)).toThrowError( + 'Username should be a valid non-empty string' + ); + expect(() => BasicCredentials.decorateRequest({} as any, '', '')).toThrowError( + 'Username should be a valid non-empty string' + ); + expect(() => BasicCredentials.decorateRequest({} as any, 'username', '')).toThrowError( + 'Password should be a valid non-empty string' + ); + expect(() => BasicCredentials.decorateRequest({} as any, '', 'password')).toThrowError( + 'Username should be a valid non-empty string' + ); }); it('`decorateRequest` correctly sets authorization header.', () => { @@ -223,8 +231,10 @@ describe('BasicAuthenticationProvider', () => { BasicCredentials.decorateRequest(oneRequest, 'one-user', 'one-password'); BasicCredentials.decorateRequest(anotherRequest, 'another-user', 'another-password'); - expect(oneRequest.headers.authorization).to.be('Basic b25lLXVzZXI6b25lLXBhc3N3b3Jk'); - expect(anotherRequest.headers.authorization).to.be('Basic YW5vdGhlci11c2VyOmFub3RoZXItcGFzc3dvcmQ='); + expect(oneRequest.headers.authorization).toBe('Basic b25lLXVzZXI6b25lLXBhc3N3b3Jk'); + expect(anotherRequest.headers.authorization).toBe( + 'Basic YW5vdGhlci11c2VyOmFub3RoZXItcGFzc3dvcmQ=' + ); }); }); }); diff --git a/x-pack/plugins/security/server/lib/authentication/providers/basic.js b/x-pack/plugins/security/server/lib/authentication/providers/basic.ts similarity index 53% rename from x-pack/plugins/security/server/lib/authentication/providers/basic.js rename to x-pack/plugins/security/server/lib/authentication/providers/basic.ts index bd8eb7a3820d8..d3756aafd0e1a 100644 --- a/x-pack/plugins/security/server/lib/authentication/providers/basic.js +++ b/x-pack/plugins/security/server/lib/authentication/providers/basic.ts @@ -4,9 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Request } from 'hapi'; +import { Cluster } from 'src/legacy/core_plugins/elasticsearch'; import { canRedirectRequest } from '../../can_redirect_request'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; +import { LoginAttempt } from '../login_attempt'; /** * Utility class that knows how to decorate request with proper Basic authentication headers. @@ -15,13 +18,13 @@ export class BasicCredentials { /** * Takes provided `username` and `password`, transforms them into proper `Basic ***` authorization * header and decorates passed request with it. - * @param {Hapi.Request} request HapiJS request instance. - * @param {string} username User name. - * @param {string} password User password. - * @returns {Hapi.Request} HapiJS request instance decorated with the proper header. + * @param request HapiJS request instance. + * @param username User name. + * @param password User password. */ - static decorateRequest(request, username, password) { - if (!request || typeof request !== 'object') { + public static decorateRequest(request: T, username: string, password: string) { + const typeOfRequest = typeof request; + if (!request || typeOfRequest !== 'object') { throw new Error('Request should be a valid object.'); } @@ -39,63 +42,59 @@ export class BasicCredentials { } } +type RequestWithLoginAttempt = Request & { + loginAttempt: () => LoginAttempt; +}; + /** - * Object that represents available provider options. - * @typedef {{ - * protocol: string, - * hostname: string, - * port: string, - * basePath: string, - * client: Client, - * log: Function - * }} ProviderOptions + * Represents available provider options. */ +interface ProviderOptions { + basePath: string; + client: Cluster; + log: (tags: string[], message: string) => void; +} /** - * Object that represents return value of internal header auth - * @typedef {{ - * authenticationResult: AuthenticationResult, - * headerNotRecognized?: boolean - * }} HeaderAuthAttempt + * The state supported by the provider. */ +interface ProviderState { + /** + * Content of the HTTP authorization header (`Basic base-64-of-username:password`) that is based + * on user credentials used at login time and that should be provided with every request to the + * Elasticsearch on behalf of the authenticated user. + */ + authorization?: string; +} /** * Provider that supports request authentication via Basic HTTP Authentication. */ +// tslint:disable-next-line: max-classes-per-file export class BasicAuthenticationProvider { - /** - * Server options that may be needed by authentication provider. - * @type {?ProviderOptions} - * @protected - */ - _options = null; - /** * Instantiates BasicAuthenticationProvider. - * @param {ProviderOptions} options Provider options object. + * @param options Provider options object. */ - constructor(options) { - this._options = options; - } + constructor(private readonly options: ProviderOptions) {} /** * Performs request authentication using Basic HTTP Authentication. - * @param {Hapi.Request} request HapiJS request instance. - * @param {Object} [state] Optional state object associated with the provider. - * @returns {Promise.} + * @param request HapiJS request instance. + * @param [state] Optional state object associated with the provider. */ - async authenticate(request, state) { - this._options.log(['debug', 'security', 'basic'], `Trying to authenticate user request to ${request.url.path}.`); + public async authenticate(request: RequestWithLoginAttempt, state?: ProviderState | null) { + this.debug(`Trying to authenticate user request to ${request.url.path}.`); // first try from login payload - let authenticationResult = await this._authenticateViaLoginAttempt(request); + let authenticationResult = await this.authenticateViaLoginAttempt(request); // if there isn't a payload, try header-based auth if (authenticationResult.notHandled()) { const { authenticationResult: headerAuthResult, headerNotRecognized, - } = await this._authenticateViaHeader(request); + } = await this.authenticateViaHeader(request); if (headerNotRecognized) { return headerAuthResult; } @@ -103,12 +102,12 @@ export class BasicAuthenticationProvider { } if (authenticationResult.notHandled() && state) { - authenticationResult = await this._authenticateViaState(request, state); + authenticationResult = await this.authenticateViaState(request, state); } else if (authenticationResult.notHandled() && canRedirectRequest(request)) { // If we couldn't handle authentication let's redirect user to the login page. const nextURL = encodeURIComponent(`${request.getBasePath()}${request.url.path}`); authenticationResult = AuthenticationResult.redirectTo( - `${this._options.basePath}/login?next=${nextURL}` + `${this.options.basePath}/login?next=${nextURL}` ); } @@ -117,39 +116,38 @@ export class BasicAuthenticationProvider { /** * Redirects user to the login page preserving query string parameters. - * @param {Hapi.Request} request HapiJS request instance. - * @returns {Promise.} + * @param request HapiJS request instance. */ - async deauthenticate(request) { + public async deauthenticate(request: Request) { // Query string may contain the path where logout has been called or // logout reason that login page may need to know. return DeauthenticationResult.redirectTo( - `${this._options.basePath}/login${request.url.search || ''}` + `${this.options.basePath}/login${request.url.search || ''}` ); } /** * Validates whether request contains a login payload and authenticates the * user if necessary. - * @param {Hapi.Request} request HapiJS request instance. - * @returns {Promise.} - * @private + * @param HapiJS request instance. */ - async _authenticateViaLoginAttempt(request) { - this._options.log(['debug', 'security', 'basic'], 'Trying to authenticate via login attempt.'); - const credentials = request.loginAttempt(request).getCredentials(); + private async authenticateViaLoginAttempt(request: RequestWithLoginAttempt) { + this.debug('Trying to authenticate via login attempt.'); + + const credentials = request.loginAttempt().getCredentials(); if (!credentials) { - this._options.log(['debug', 'security', 'basic'], 'Username and password not found in payload.'); + this.debug('Username and password not found in payload.'); return AuthenticationResult.notHandled(); } + try { const { username, password } = credentials; BasicCredentials.decorateRequest(request, username, password); - const user = await this._options.client.callWithRequest(request, 'shield.authenticate'); - this._options.log(['debug', 'security', 'basic'], 'Request has been authenticated via login attempt.'); + const user = await this.options.client.callWithRequest(request, 'shield.authenticate'); + this.debug('Request has been authenticated via login attempt.'); return AuthenticationResult.succeeded(user, { authorization: request.headers.authorization }); - } catch(err) { - this._options.log(['debug', 'security', 'basic'], `Failed to authenticate request via login attempt: ${err.message}`); + } catch (err) { + this.debug(`Failed to authenticate request via login attempt: ${err.message}`); // Reset `Authorization` header we've just set. We know for sure that it hasn't been defined before, // otherwise it would have been used or completely rejected by the `authenticateViaHeader`. // We can't just set `authorization` to `undefined` or `null`, we should remove this property @@ -163,72 +161,62 @@ export class BasicAuthenticationProvider { /** * Validates whether request contains `Basic ***` Authorization header and just passes it * forward to Elasticsearch backend. - * @param {Hapi.Request} request HapiJS request instance. - * @returns {Promise.} - * @private + * @param request HapiJS request instance. */ - async _authenticateViaHeader(request) { - this._options.log(['debug', 'security', 'basic'], 'Trying to authenticate via header.'); + private async authenticateViaHeader(request: Request) { + this.debug('Trying to authenticate via header.'); const authorization = request.headers.authorization; if (!authorization) { - this._options.log(['debug', 'security', 'basic'], 'Authorization header is not presented.'); - return { - authenticationResult: AuthenticationResult.notHandled() - }; + this.debug('Authorization header is not presented.'); + return { authenticationResult: AuthenticationResult.notHandled() }; } const authenticationSchema = authorization.split(/\s+/)[0]; if (authenticationSchema.toLowerCase() !== 'basic') { - this._options.log(['debug', 'security', 'basic'], `Unsupported authentication schema: ${authenticationSchema}`); + this.debug(`Unsupported authentication schema: ${authenticationSchema}`); return { authenticationResult: AuthenticationResult.notHandled(), - headerNotRecognized: true + headerNotRecognized: true, }; } try { - const user = await this._options.client.callWithRequest(request, 'shield.authenticate'); + const user = await this.options.client.callWithRequest(request, 'shield.authenticate'); - this._options.log(['debug', 'security', 'basic'], 'Request has been authenticated via header.'); + this.debug('Request has been authenticated via header.'); - return { - authenticationResult: AuthenticationResult.succeeded(user) - }; - } catch(err) { - this._options.log(['debug', 'security', 'basic'], `Failed to authenticate request via header: ${err.message}`); - return { - authenticationResult: AuthenticationResult.failed(err) - }; + return { authenticationResult: AuthenticationResult.succeeded(user) }; + } catch (err) { + this.debug(`Failed to authenticate request via header: ${err.message}`); + return { authenticationResult: AuthenticationResult.failed(err) }; } } /** * Tries to extract authorization header from the state and adds it to the request before * it's forwarded to Elasticsearch backend. - * @param {Hapi.Request} request HapiJS request instance. - * @param {Object} state State value previously stored by the provider. - * @returns {Promise.} - * @private + * @param request HapiJS request instance. + * @param state State value previously stored by the provider. */ - async _authenticateViaState(request, { authorization }) { - this._options.log(['debug', 'security', 'basic'], 'Trying to authenticate via state.'); + private async authenticateViaState(request: Request, { authorization }: ProviderState) { + this.debug('Trying to authenticate via state.'); if (!authorization) { - this._options.log(['debug', 'security', 'basic'], 'Access token is not found in state.'); + this.debug('Access token is not found in state.'); return AuthenticationResult.notHandled(); } request.headers.authorization = authorization; try { - const user = await this._options.client.callWithRequest(request, 'shield.authenticate'); + const user = await this.options.client.callWithRequest(request, 'shield.authenticate'); - this._options.log(['debug', 'security', 'basic'], 'Request has been authenticated via state.'); + this.debug('Request has been authenticated via state.'); return AuthenticationResult.succeeded(user); - } catch(err) { - this._options.log(['debug', 'security', 'basic'], `Failed to authenticate request via state: ${err.message}`); + } catch (err) { + this.debug(`Failed to authenticate request via state: ${err.message}`); // Reset `Authorization` header we've just set. We know for sure that it hasn't been defined before, // otherwise it would have been used or completely rejected by the `authenticateViaHeader`. @@ -240,4 +228,12 @@ export class BasicAuthenticationProvider { return AuthenticationResult.failed(err); } } + + /** + * Logs message with `debug` level and saml/security related tags. + * @param message Message to log. + */ + private debug(message: string) { + this.options.log(['debug', 'security', 'basic'], message); + } } From 9d60ad3831d6a3dd1c48a4eeb0d067dae38579ab Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 28 Mar 2019 17:57:46 +0100 Subject: [PATCH 85/96] [ML] Reverts completely resetting explorer state on job selection change. (#34084) --- x-pack/plugins/ml/public/explorer/explorer.js | 78 +++++++++---------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/x-pack/plugins/ml/public/explorer/explorer.js b/x-pack/plugins/ml/public/explorer/explorer.js index 444cdf5acc721..b359ea09dddb7 100644 --- a/x-pack/plugins/ml/public/explorer/explorer.js +++ b/x-pack/plugins/ml/public/explorer/explorer.js @@ -254,50 +254,48 @@ export const Explorer = injectI18n(injectObservablesAsProps( // Listen for changes to job selection. if (action === EXPLORER_ACTION.JOB_SELECTION_CHANGE) { - this.setState(...getExplorerDefaultState(), async () => { - const { selectedJobs } = payload; - const stateUpdate = { - noInfluencersConfigured: (getInfluencers(selectedJobs).length === 0), - selectedJobs, + const { selectedJobs } = payload; + const stateUpdate = { + noInfluencersConfigured: (getInfluencers(selectedJobs).length === 0), + selectedJobs, + }; + + this.props.appStateHandler(APP_STATE_ACTION.CLEAR_SELECTION); + Object.assign(stateUpdate, getClearedSelectedAnomaliesState()); + // clear filter if selected jobs have no influencers + if (stateUpdate.noInfluencersConfigured === true) { + this.props.appStateHandler(APP_STATE_ACTION.CLEAR_INFLUENCER_FILTER_SETTINGS); + const noFilterState = { + filterActive: false, + filteredFields: [], + influencersFilterQuery: undefined, + maskAll: false, + queryString: '', + tableQueryString: '' }; - this.props.appStateHandler(APP_STATE_ACTION.CLEAR_SELECTION); - Object.assign(stateUpdate, getClearedSelectedAnomaliesState()); - // clear filter if selected jobs have no influencers - if (stateUpdate.noInfluencersConfigured === true) { - this.props.appStateHandler(APP_STATE_ACTION.CLEAR_INFLUENCER_FILTER_SETTINGS); - const noFilterState = { - filterActive: false, - filteredFields: [], - influencersFilterQuery: undefined, - maskAll: false, - queryString: '', - tableQueryString: '' - }; - - Object.assign(stateUpdate, noFilterState); - } else { - // indexPattern will not be used if there are no influencers so set up can be skipped - // indexPattern is passed to KqlFilterBar which is only shown if (noInfluencersConfigured === false) - const indexPattern = await this.getIndexPattern(selectedJobs); - stateUpdate.indexPattern = indexPattern; - } + Object.assign(stateUpdate, noFilterState); + } else { + // indexPattern will not be used if there are no influencers so set up can be skipped + // indexPattern is passed to KqlFilterBar which is only shown if (noInfluencersConfigured === false) + const indexPattern = await this.getIndexPattern(selectedJobs); + stateUpdate.indexPattern = indexPattern; + } - if (selectedJobs.length > 1) { - this.props.appStateHandler( - APP_STATE_ACTION.SAVE_SWIMLANE_VIEW_BY_FIELD_NAME, - { swimlaneViewByFieldName: VIEW_BY_JOB_LABEL }, - ); - stateUpdate.swimlaneViewByFieldName = VIEW_BY_JOB_LABEL; - // enforce a state update for swimlaneViewByFieldName - this.setState({ swimlaneViewByFieldName: VIEW_BY_JOB_LABEL }, () => { - this.updateExplorer(stateUpdate, true); - }); - return; - } + if (selectedJobs.length > 1) { + this.props.appStateHandler( + APP_STATE_ACTION.SAVE_SWIMLANE_VIEW_BY_FIELD_NAME, + { swimlaneViewByFieldName: VIEW_BY_JOB_LABEL }, + ); + stateUpdate.swimlaneViewByFieldName = VIEW_BY_JOB_LABEL; + // enforce a state update for swimlaneViewByFieldName + this.setState({ swimlaneViewByFieldName: VIEW_BY_JOB_LABEL }, () => { + this.updateExplorer(stateUpdate, true); + }); + return; + } - this.updateExplorer(stateUpdate, true); - }); + this.updateExplorer(stateUpdate, true); } // RELOAD reloads full Anomaly Explorer and clears the selection. From b4bafa5ff638e7922a16e391b665be7226bbdde2 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 28 Mar 2019 10:13:10 -0700 Subject: [PATCH 86/96] Allow negative values for custom ranges in metric and gauge visualizations (#33814) * Fix inequality directives to handle negative values * Fix test --- .../public/controls/gauge_options.html | 4 +- .../public/controls/gauge_options.js | 2 +- .../public/controls/heatmap_options.html | 2 +- .../public/controls/heatmap_options.js | 2 +- .../controls/point_series/value_axes.html | 4 +- .../public/controls/point_series_options.html | 6 +-- .../metric_vis/public/metric_vis_params.html | 4 +- .../metric_vis/public/metric_vis_params.js | 2 +- .../public/directives/__tests__/inequality.js | 37 ++++++++++++++++++- src/legacy/ui/public/directives/inequality.js | 21 ++++++----- 10 files changed, 61 insertions(+), 23 deletions(-) diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/gauge_options.html b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/gauge_options.html index d22a34cfad1ee..9d29f390ac358 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/gauge_options.html +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/gauge_options.html @@ -173,7 +173,7 @@ type="number" class="form-control" name="range.from" - greater-or-equal-than="{{getGreaterThan($index)}}" + greater-or-equal-than="getGreaterThan($index)" required step="any" /> @@ -184,7 +184,7 @@ type="number" class="form-control" name="range.to" - greater-or-equal-than="{{range.from}}" + greater-or-equal-than="range.from" required step="any" /> diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/gauge_options.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/gauge_options.js index 7da9d16b7f74a..b036741291eb5 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/gauge_options.js +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/gauge_options.js @@ -81,7 +81,7 @@ module.directive('gaugeOptions', function (i18n) { }; $scope.getGreaterThan = function (index) { - if (index === 0) return 0; + if (index === 0) return -Infinity; return $scope.editorState.params.gauge.colorsRange[index - 1].to; }; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.html b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.html index 7a56e2ce8f0ef..0eaa3477bbb11 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.html +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.html @@ -161,7 +161,7 @@ type="number" class="form-control" name="range.from" - greater-or-equal-than="{{getGreaterThan($index)}}" + greater-or-equal-than="getGreaterThan($index)" step="any" /> diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.js index a96a27cb4b71e..6a4839abb5354 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.js +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/heatmap_options.js @@ -64,7 +64,7 @@ module.directive('heatmapOptions', function (i18n) { }; $scope.getGreaterThan = function (index) { - if (index === 0) return; + if (index === 0) return -Infinity; return $scope.editorState.params.colorsRange[index - 1].to; }; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.html b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.html index fb62021a51c93..5fb086585a244 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.html +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series/value_axes.html @@ -284,6 +284,7 @@ class="kuiInput visEditorSidebar__input" type="number" step="0.1" + greater-than="axis.scale.min" ng-model="axis.scale.max" >
    @@ -301,7 +302,8 @@ class="kuiInput visEditorSidebar__input" type="number" step="0.1" - greater-than="{{axis.scale.type === 'log' ? 0 : ''}}" + greater-than="axis.scale.type === 'log' ? 0 : undefined" + less-than="axis.scale.max" ng-model="axis.scale.min" >
    diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series_options.html b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series_options.html index ff4d30837c8de..b4ebf8ebbd481 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series_options.html +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controls/point_series_options.html @@ -17,7 +17,7 @@ class="form-control" type="number" step="0.1" - greater-than="{{editorState.params.yAxis.min}}" + greater-than="editorState.params.yAxis.min" ng-model="editorState.params.yAxis.max" ng-required="editorState.params.setYExtents"> @@ -30,8 +30,8 @@ class="form-control" type="number" step="0.1" - less-than="{{editorState.params.yAxis.max}}" - greater-than="{{editorState.params.scale === 'log' ? 0 : ''}}" + less-than="editorState.params.yAxis.max" + greater-than="editorState.params.scale === 'log' ? 0 : undefined" ng-model="editorState.params.yAxis.min" ng-required="editorState.params.setYExtents"> diff --git a/src/legacy/core_plugins/metric_vis/public/metric_vis_params.html b/src/legacy/core_plugins/metric_vis/public/metric_vis_params.html index c11d0bd8b111b..6efdd60faf4ed 100644 --- a/src/legacy/core_plugins/metric_vis/public/metric_vis_params.html +++ b/src/legacy/core_plugins/metric_vis/public/metric_vis_params.html @@ -78,7 +78,7 @@ type="number" class="form-control" name="range.from" - greater-or-equal-than="{{getGreaterThan($index)}}" + greater-or-equal-than="getGreaterThan($index)" required step="any" /> @@ -89,7 +89,7 @@ type="number" class="form-control" name="range.to" - greater-or-equal-than="{{range.from}}" + greater-or-equal-than="range.from" required step="any" /> diff --git a/src/legacy/core_plugins/metric_vis/public/metric_vis_params.js b/src/legacy/core_plugins/metric_vis/public/metric_vis_params.js index f51678504441a..20ad8954f9617 100644 --- a/src/legacy/core_plugins/metric_vis/public/metric_vis_params.js +++ b/src/legacy/core_plugins/metric_vis/public/metric_vis_params.js @@ -55,7 +55,7 @@ module.directive('metricVisParams', function (i18n) { }; $scope.getGreaterThan = function (index) { - if (index === 0) return 0; + if (index === 0) return -Infinity; return $scope.editorState.params.metric.colorsRange[index - 1].to; }; diff --git a/src/legacy/ui/public/directives/__tests__/inequality.js b/src/legacy/ui/public/directives/__tests__/inequality.js index d503d406fdbff..0e6a537d69f7c 100644 --- a/src/legacy/ui/public/directives/__tests__/inequality.js +++ b/src/legacy/ui/public/directives/__tests__/inequality.js @@ -33,7 +33,6 @@ describe('greater_than model validator directive', function () { $rootScope = _$rootScope_; })); - // no value is the same as 0 describe('without value', function () { let element; beforeEach(function () { @@ -60,6 +59,33 @@ describe('greater_than model validator directive', function () { }); }); + describe('with string values', function () { + let element; + beforeEach(function () { + html = ``; + element = $compile(html)($rootScope); + }); + + it('should be valid for greater than 10', function () { + $rootScope.value = '15'; + $rootScope.$digest(); + expect(element.hasClass('ng-valid')).to.be.ok(); + }); + + it('should be invalid for 10', function () { + $rootScope.value = '10'; + $rootScope.$digest(); + expect(element.hasClass('ng-invalid')).to.be.ok(); + }); + + // Edge case because '5' > '10' as strings + it('should be invalid less than 10', function () { + $rootScope.value = '5'; + $rootScope.$digest(); + expect(element.hasClass('ng-invalid')).to.be.ok(); + }); + }); + [0, 1, 10, 42, -12].forEach(function (num) { describe('with value ' + num, function () { let element; @@ -85,7 +111,14 @@ describe('greater_than model validator directive', function () { $rootScope.$digest(); expect(element.hasClass('ng-invalid')).to.be.ok(); }); + + it('should be valid for empty model values', () => { + [undefined, null, ''].forEach(val => { + $rootScope.value = val; + $rootScope.$digest(); + expect(element.hasClass('ng-valid')).to.be.ok(); + }); + }); }); }); - }); diff --git a/src/legacy/ui/public/directives/inequality.js b/src/legacy/ui/public/directives/inequality.js index d3c80d1ff2e96..a08b617ceb929 100644 --- a/src/legacy/ui/public/directives/inequality.js +++ b/src/legacy/ui/public/directives/inequality.js @@ -24,12 +24,7 @@ function makeDirectiveDef(id, compare) { return { require: 'ngModel', link: function ($scope, $el, $attr, ngModel) { - const getBound = function () { return $parse($attr[id])(); }; - const defaultVal = { - 'greaterThan': -Infinity, - 'greaterOrEqualThan': -Infinity, - 'lessThan': Infinity - }[id]; + const getBound = function () { return $parse($attr[id])($scope); }; ngModel.$parsers.push(validate); ngModel.$formatters.push(validate); @@ -38,12 +33,20 @@ function makeDirectiveDef(id, compare) { validate(ngModel.$viewValue); }); + // We only set it to invalid when both the model value and the value to compare against are + // provided, and the values do not meet the condition. function validate(val) { - const bound = !isNaN(getBound()) ? +getBound() : defaultVal; - const valid = !isNaN(bound) && !isNaN(val) && compare(val, bound); - ngModel.$setValidity(id, valid); + const bound = getBound(); + const left = parseFloat(val); + const right = parseFloat(bound); + const isValid = isEmpty(val) || isEmpty(bound) || compare(left, right); + ngModel.$setValidity(id, isValid); return val; } + + function isEmpty(val) { + return typeof val === 'undefined' || val === null || val === ''; + } } }; }; From edbc3d49a718d0234907888ffdc983413cfe6ccd Mon Sep 17 00:00:00 2001 From: Sarah Hersh Date: Thu, 28 Mar 2019 13:16:28 -0400 Subject: [PATCH 87/96] [DOCS]Update UI names in Reporting doc (#34073) --- .../automating-report-generation.asciidoc | 19 ++++++++++--------- docs/reporting/getting-started.asciidoc | 3 +-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/reporting/automating-report-generation.asciidoc b/docs/reporting/automating-report-generation.asciidoc index 070d69c04cc52..02fa2c97f37f2 100644 --- a/docs/reporting/automating-report-generation.asciidoc +++ b/docs/reporting/automating-report-generation.asciidoc @@ -1,11 +1,11 @@ [role="xpack"] [[automating-report-generation]] == Automating Report Generation -You can automatically generate reports with a watch, or by submitting +You can automatically generate reports with {watcher}, or by submitting HTTP POST requests from a script. To automatically generate reports with a watch, you need to configure -{watcher} to trust the Kibana server’s certificate. For more information, +{watcher} to trust the {kib} server’s certificate. For more information, see <>. include::report-intervals.asciidoc[] @@ -13,27 +13,28 @@ include::report-intervals.asciidoc[] To get the URL for triggering a report generation during a given time period: . Load the saved object. -. Use the time-picker to specify a relative or absolute time period. -. Click *Reporting* in the Kibana toolbar. -. Copy the displayed **Generation URL**. +. Use the timepicker to specify a relative or absolute time period. +. Click *Share* in the Kibana toolbar. +. Select *PDF Reports*. +. Click **Copy POST URL**. NOTE: The response from this request with be JSON, and will contain a `path` property with a URL to use to download the generated report. When requesting that path, you will get a 503 response if it's not completed yet. In this case, retry after the -number of seconds in the `Retry-After` header in the response until you get the PDF. +number of seconds in the `Retry-After` header in the response until the PDF is returned. To configure a watch to email reports, you use the `reporting` attachment type in an `email` action. For more information, see -{xpack-ref}/actions-email.html#configuring-email[Configuring Email Accounts]. +{stack-ov}/actions-email.html#configuring-email[Configuring Email Accounts]. include::watch-example.asciidoc[] For more information about configuring watches, see -{xpack-ref}/how-watcher-works.html[How Watcher Works]. +{stack-ov}/how-watcher-works.html[How Watcher Works]. == Deprecated Report URLs -The following is deprecated in 6.0, and you should now use Kibana to get the URL for a +The following is deprecated in 6.0, and you should now use {kib} to get the URL for a particular report. You may request PDF reports optimized for printing through three {reporting} endpoints: diff --git a/docs/reporting/getting-started.asciidoc b/docs/reporting/getting-started.asciidoc index 1c616731f3bba..0bdb9d3d3f9f6 100644 --- a/docs/reporting/getting-started.asciidoc +++ b/docs/reporting/getting-started.asciidoc @@ -49,5 +49,4 @@ image:reporting/images/share-button.png["Reporting Button",link="share-button.pn === Generating a Report Automatically If you want to automatically generate reports from a script or with -{watcher}, use the displayed Generation URL. For more information, see -<> +{watcher}, see <> From 1d2fbf827c978b1611169e3f256f36a35193182f Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Thu, 28 Mar 2019 10:17:35 -0700 Subject: [PATCH 88/96] [DOCS] Fixes anchor in ordered list (#34092) --- docs/security/securing-kibana.asciidoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/security/securing-kibana.asciidoc b/docs/security/securing-kibana.asciidoc index 85c71f1c2d4aa..51c796e7fe9e2 100644 --- a/docs/security/securing-kibana.asciidoc +++ b/docs/security/securing-kibana.asciidoc @@ -73,8 +73,7 @@ xpack.security.sessionTimeout: 600000 . Restart {kib}. -[[kibana-roles]] -. Choose an authentication mechanism and grant users the privileges they need to +. [[kibana-roles]]Choose an authentication mechanism and grant users the privileges they need to use {kib}. + -- From d6eb59179f760f59e2799a8b7d249f8f91a9f121 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 28 Mar 2019 11:38:33 -0600 Subject: [PATCH 89/96] [Maps] apply filters to join SearchSource request (#34072) * [Maps] apply filters to join SearchSource request * add functional test verify filter applied to join in dashboard --- .../shared/layers/sources/es_join_source.js | 43 +++---------------- .../public/shared/layers/sources/es_source.js | 25 ++++++----- .../maps/public/shared/layers/vector_layer.js | 4 +- .../apps/maps/embeddable/dashboard.js | 27 ++++++++++-- 4 files changed, 42 insertions(+), 57 deletions(-) diff --git a/x-pack/plugins/maps/public/shared/layers/sources/es_join_source.js b/x-pack/plugins/maps/public/shared/layers/sources/es_join_source.js index ba8e9dbc278fb..de911fdb8dda4 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/es_join_source.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/es_join_source.js @@ -8,12 +8,7 @@ import _ from 'lodash'; import { AbstractESSource } from './es_source'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { - fetchSearchSourceAndRecordWithInspector, - SearchSource, -} from '../../../kibana_services'; import { AggConfigs } from 'ui/vis/agg_configs'; -import { timefilter } from 'ui/timefilter/timefilter'; import { i18n } from '@kbn/i18n'; const TERMS_AGG_NAME = 'join'; @@ -96,42 +91,14 @@ export class ESJoinSource extends AbstractESSource { } const indexPattern = await this._getIndexPattern(); - const timeAware = await this.isTimeAware(); - + const searchSource = await this._makeSearchSource(searchFilters, 0); const configStates = this._makeAggConfigs(); const aggConfigs = new AggConfigs(indexPattern, configStates, aggSchemas.all); + searchSource.setField('aggs', aggConfigs.toDsl()); - let rawEsData; - try { - const searchSource = new SearchSource(); - searchSource.setField('index', indexPattern); - searchSource.setField('size', 0); - searchSource.setField('filter', () => { - const filters = []; - if (timeAware) { - filters.push(timefilter.createFilter(indexPattern, searchFilters.timeFilters)); - } - return filters; - }); - searchSource.setField('query', searchFilters.query); - - const dsl = aggConfigs.toDsl(); - searchSource.setField('aggs', dsl); - rawEsData = await fetchSearchSourceAndRecordWithInspector({ - inspectorAdapters: this._inspectorAdapters, - searchSource, - requestName: `${this._descriptor.indexPatternTitle}.${this._descriptor.term}`, - requestId: this._descriptor.id, - requestDesc: this.getJoinDescription(leftSourceName, leftFieldName), - }); - } catch (error) { - throw new Error(i18n.translate('xpack.maps.source.esJoin.errorMessage', { - defaultMessage: `Elasticsearch search request failed, error: {message}`, - values: { - message: error.message - } - })); - } + const requestName = `${this._descriptor.indexPatternTitle}.${this._descriptor.term}`; + const requestDesc = this.getJoinDescription(leftSourceName, leftFieldName); + const rawEsData = await this._runEsQuery(requestName, searchSource, requestDesc); const metricPropertyNames = configStates .filter(configState => { diff --git a/x-pack/plugins/maps/public/shared/layers/sources/es_source.js b/x-pack/plugins/maps/public/shared/layers/sources/es_source.js index 54d8181f2682e..54a83360fea3a 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/es_source.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/es_source.js @@ -131,12 +131,12 @@ export class AbstractESSource extends AbstractVectorSource { } - async _runEsQuery(layerName, searchSource, requestDescription) { + async _runEsQuery(requestName, searchSource, requestDescription) { try { return await fetchSearchSourceAndRecordWithInspector({ inspectorAdapters: this._inspectorAdapters, searchSource, - requestName: layerName, + requestName, requestId: this._descriptor.id, requestDesc: requestDescription }); @@ -150,21 +150,20 @@ export class AbstractESSource extends AbstractVectorSource { async _makeSearchSource(searchFilters, limit) { const indexPattern = await this._getIndexPattern(); - const geoField = await this._getGeoField(); const isTimeAware = await this.isTimeAware(); + const allFilters = [...searchFilters.filters]; + if (this.isFilterByMapBounds() && searchFilters.buffer) {//buffer can be empty + const geoField = await this._getGeoField(); + allFilters.push(createExtentFilter(searchFilters.buffer, geoField.name, geoField.type)); + } + if (isTimeAware) { + allFilters.push(timefilter.createFilter(indexPattern, searchFilters.timeFilters)); + } + const searchSource = new SearchSource(); searchSource.setField('index', indexPattern); searchSource.setField('size', limit); - searchSource.setField('filter', () => { - const allFilters = [...searchFilters.filters]; - if (this.isFilterByMapBounds() && searchFilters.buffer) {//buffer can be empty - allFilters.push(createExtentFilter(searchFilters.buffer, geoField.name, geoField.type)); - } - if (isTimeAware) { - allFilters.push(timefilter.createFilter(indexPattern, searchFilters.timeFilters)); - } - return allFilters; - }); + searchSource.setField('filter', allFilters); searchSource.setField('query', searchFilters.query); if (searchFilters.layerQuery) { diff --git a/x-pack/plugins/maps/public/shared/layers/vector_layer.js b/x-pack/plugins/maps/public/shared/layers/vector_layer.js index 1d9d97e65079a..d2736b04f77bd 100644 --- a/x-pack/plugins/maps/public/shared/layers/vector_layer.js +++ b/x-pack/plugins/maps/public/shared/layers/vector_layer.js @@ -228,7 +228,7 @@ export class VectorLayer extends AbstractLayer { && !updateDueToPrecisionChange; } - async _syncJoin(join, { startLoading, stopLoading, onLoadError, dataFilters }) { + async _syncJoin({ join, startLoading, stopLoading, onLoadError, dataFilters }) { const joinSource = join.getJoinSource(); const sourceDataId = join.getSourceId(); @@ -269,7 +269,7 @@ export class VectorLayer extends AbstractLayer { async _syncJoins({ startLoading, stopLoading, onLoadError, dataFilters }) { const joinSyncs = this.getValidJoins().map(async join => { - return this._syncJoin(join, { startLoading, stopLoading, onLoadError, dataFilters }); + return this._syncJoin({ join, startLoading, stopLoading, onLoadError, dataFilters }); }); return await Promise.all(joinSyncs); } diff --git a/x-pack/test/functional/apps/maps/embeddable/dashboard.js b/x-pack/test/functional/apps/maps/embeddable/dashboard.js index 0fecfd71f3d14..f458c38093e4f 100644 --- a/x-pack/test/functional/apps/maps/embeddable/dashboard.js +++ b/x-pack/test/functional/apps/maps/embeddable/dashboard.js @@ -12,16 +12,24 @@ export default function ({ getPageObjects, getService }) { const filterBar = getService('filterBar'); const dashboardPanelActions = getService('dashboardPanelActions'); const inspector = getService('inspector'); + const testSubjects = getService('testSubjects'); describe('embed in dashboard', () => { before(async () => { await kibanaServer.uiSettings.replace({ - 'defaultIndex': 'c698b940-e149-11e8-a35a-370a8516603a' + 'defaultIndex': 'c698b940-e149-11e8-a35a-370a8516603a', + 'courier:ignoreFilterIfFieldNotInIndex': true }); await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.loadSavedDashboard('map embeddable example'); }); + after(async () => { + await kibanaServer.uiSettings.replace({ + 'courier:ignoreFilterIfFieldNotInIndex': false + }); + }); + async function getRequestTimestamp() { await inspector.openInspectorRequestsView(); const requestStats = await inspector.getTableData(); @@ -58,11 +66,22 @@ export default function ({ getPageObjects, getService }) { it('should apply new container state (time, query, filters) to embeddable', async () => { await filterBar.selectIndexPattern('logstash-*'); await filterBar.addFilter('machine.os', 'is', 'win 8'); + await filterBar.selectIndexPattern('meta_for_geo_shapes*'); + await filterBar.addFilter('shape_name', 'is', 'alpha'); + await dashboardPanelActions.openInspectorByTitle('geo grid vector grid example'); - const requestStats = await inspector.getTableData(); - const totalHits = PageObjects.maps.getInspectorStatRowHit(requestStats, 'Hits (total)'); + const geoGridRequestStats = await inspector.getTableData(); + const geoGridTotalHits = PageObjects.maps.getInspectorStatRowHit(geoGridRequestStats, 'Hits (total)'); + await inspector.close(); + expect(geoGridTotalHits).to.equal('1'); + + await dashboardPanelActions.openInspectorByTitle('join example'); + await testSubjects.click('inspectorRequestChooser'); + await testSubjects.click('inspectorRequestChoosermeta_for_geo_shapes*.shape_name'); + const joinRequestStats = await inspector.getTableData(); + const joinTotalHits = PageObjects.maps.getInspectorStatRowHit(joinRequestStats, 'Hits (total)'); await inspector.close(); - expect(totalHits).to.equal('1'); + expect(joinTotalHits).to.equal('3'); }); it('should re-fetch query when "refresh" is clicked', async () => { From 8ff80cb589f4c73d7acef02b7e8623a5be71e3ca Mon Sep 17 00:00:00 2001 From: Matt Apperson Date: Thu, 28 Mar 2019 13:54:46 -0400 Subject: [PATCH 90/96] [BeatsCM] Move API to new return format (#31660) * add and assign types * move error management to the lib vs each route. More DRY and easier to test * move more endpoints to the new format * fix result for not-yet-pages beats list * refine more endpoints * move more routes to new format * UI now propperly connected to the API * uodate tests and documenting testing in readme --- .../beats_management/common/return_types.ts | 116 ++++++++++++++++++ .../public/components/config_list.tsx | 4 +- .../public/components/tag/tag_edit.tsx | 2 +- .../lib/adapters/beats/adapter_types.ts | 5 +- .../adapters/beats/memory_beats_adapter.ts | 17 ++- .../lib/adapters/beats/rest_beats_adapter.ts | 52 ++++---- .../configuration_blocks/adapter_types.ts | 15 +-- .../memory_config_blocks_adapter.ts | 26 ++-- .../rest_config_blocks_adapter.ts | 27 ++-- .../lib/adapters/tags/rest_tags_adapter.ts | 20 ++- .../adapters/tokens/rest_tokens_adapter.ts | 12 +- .../beats_management/public/lib/beats.ts | 12 +- .../public/lib/configuration_blocks.ts | 2 +- .../public/pages/beat/details.tsx | 2 +- .../public/pages/tag/create.tsx | 6 +- .../public/pages/tag/edit.tsx | 13 +- .../public/pages/walkthrough/initial/tag.tsx | 9 +- x-pack/plugins/beats_management/readme.md | 29 +++-- .../lib/adapters/framework/adapter_types.ts | 2 +- .../beats_management/server/lib/beats.ts | 1 - .../beats_management/server/lib/framework.ts | 109 +++++++++++++--- .../__tests__/beats_assignments.test.ts | 16 +-- .../server/rest_api/beats/configuration.ts | 54 ++++---- .../server/rest_api/beats/enroll.ts | 59 ++++----- .../server/rest_api/beats/events.ts | 34 +++-- .../server/rest_api/beats/get.ts | 30 ++--- .../server/rest_api/beats/list.ts | 35 +++--- .../server/rest_api/beats/tag_assignment.ts | 32 +++-- .../server/rest_api/beats/tag_removal.ts | 32 +++-- .../server/rest_api/beats/update.ts | 63 ++++++---- .../server/rest_api/configurations/delete.ts | 20 +-- .../server/rest_api/configurations/get.ts | 28 ++--- .../server/rest_api/configurations/upsert.ts | 34 ++--- .../server/rest_api/tags/assignable.ts | 24 ++-- .../server/rest_api/tags/delete.ts | 19 +-- .../server/rest_api/tags/get.ts | 19 ++- .../server/rest_api/tags/list.ts | 19 ++- .../server/rest_api/tags/set.ts | 16 ++- .../server/rest_api/tokens/create.ts | 23 +++- .../server/utils/error_wrappers/index.ts | 7 -- .../error_wrappers/wrap_es_error.test.ts | 42 ------- .../utils/error_wrappers/wrap_es_error.ts | 24 ---- .../apis/beats/assign_tags_to_beats.js | 40 +++--- .../apis/beats/create_enrollment_tokens.js | 4 +- .../api_integration/apis/beats/enroll_beat.js | 22 ++-- .../api_integration/apis/beats/get_beat.js | 4 +- .../test/api_integration/apis/beats/index.js | 9 +- .../api_integration/apis/beats/list_beats.js | 4 +- .../apis/beats/remove_tags_from_beats.js | 38 +++--- .../api_integration/apis/beats/set_config.js | 2 +- .../api_integration/apis/beats/update_beat.js | 14 ++- 51 files changed, 721 insertions(+), 527 deletions(-) create mode 100644 x-pack/plugins/beats_management/common/return_types.ts delete mode 100644 x-pack/plugins/beats_management/server/utils/error_wrappers/index.ts delete mode 100644 x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.test.ts delete mode 100644 x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.ts diff --git a/x-pack/plugins/beats_management/common/return_types.ts b/x-pack/plugins/beats_management/common/return_types.ts new file mode 100644 index 0000000000000..a7125795a5c7d --- /dev/null +++ b/x-pack/plugins/beats_management/common/return_types.ts @@ -0,0 +1,116 @@ +/* + * 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. + */ + +export interface BaseReturnType { + error?: { + message: string; + code?: number; + }; + success: boolean; +} + +export interface ReturnTypeCreate extends BaseReturnType { + item: T; + action: 'created'; +} + +export interface ReturnTypeUpdate extends BaseReturnType { + item: T; + action: 'updated'; +} + +export interface ReturnTypeBulkCreate extends BaseReturnType { + results: Array<{ + item: T; + success: boolean; + action: 'created'; + error?: { + message: string; + code?: number; + }; + }>; +} + +// delete +export interface ReturnTypeDelete extends BaseReturnType { + action: 'deleted'; +} + +export interface ReturnTypeBulkDelete extends BaseReturnType { + results: Array<{ + success: boolean; + action: 'deleted'; + error?: { + message: string; + code?: number; + }; + }>; +} + +// upsert +export interface ReturnTypeUpsert extends BaseReturnType { + item: T; + action: 'created' | 'updated'; +} + +// upsert bulk +export interface ReturnTypeBulkUpsert extends BaseReturnType { + results: Array<{ + success: boolean; + action: 'created' | 'updated'; + error?: { + message: string; + code?: number; + }; + }>; +} + +// list +export interface ReturnTypeList extends BaseReturnType { + list: T[]; + page: number; + total: number; +} + +// get +export interface ReturnTypeGet extends BaseReturnType { + item: T; +} + +export interface ReturnTypeBulkGet extends BaseReturnType { + items: T[]; +} + +// action -- e.g. validate config block. Like ES simulate endpoint +export interface ReturnTypeAction extends BaseReturnType { + result: { + [key: string]: any; + }; +} +// e.g. +// { +// result: { +// username: { valid: true }, +// password: { valid: false, error: 'something' }, +// hosts: [ +// { valid: false }, { valid: true }, +// ] +// } +// } + +// bulk action -- e.g. assign tags to beats +export interface ReturnTypeBulkAction extends BaseReturnType { + results?: Array<{ + success: boolean; + result?: { + [key: string]: any; + }; + error?: { + message: string; + code?: number; + }; + }>; +} diff --git a/x-pack/plugins/beats_management/public/components/config_list.tsx b/x-pack/plugins/beats_management/public/components/config_list.tsx index ed5c925ef950b..f860188e66800 100644 --- a/x-pack/plugins/beats_management/public/components/config_list.tsx +++ b/x-pack/plugins/beats_management/public/components/config_list.tsx @@ -15,7 +15,7 @@ import { ConfigurationBlock } from '../../common/domain_types'; interface ComponentProps { configs: { error?: string | undefined; - blocks: ConfigurationBlock[]; + list: ConfigurationBlock[]; page: number; total: number; }; @@ -30,7 +30,7 @@ const pagination = { const ConfigListUi: React.SFC = props => ( ; update(id: string, beatData: Partial): Promise; getBeatsWithTag(tagId: string): Promise; getAll(ESQuery?: any): Promise; - removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise; - assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise; + removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise; + assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise; getBeatWithToken(enrollmentToken: string): Promise; } diff --git a/x-pack/plugins/beats_management/public/lib/adapters/beats/memory_beats_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/beats/memory_beats_adapter.ts index 21aa092ef8440..319e37e226c9e 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/beats/memory_beats_adapter.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/beats/memory_beats_adapter.ts @@ -5,14 +5,9 @@ */ import { omit } from 'lodash'; - import { CMBeat } from '../../../../common/domain_types'; -import { - BeatsRemovalReturn, - BeatsTagAssignment, - CMAssignmentReturn, - CMBeatsAdapter, -} from './adapter_types'; +import { ReturnTypeBulkAction } from '../../../../common/return_types'; +import { BeatsTagAssignment, CMBeatsAdapter } from './adapter_types'; export class MemoryBeatsAdapter implements CMBeatsAdapter { private beatsDB: CMBeat[]; @@ -46,7 +41,9 @@ export class MemoryBeatsAdapter implements CMBeatsAdapter { public async getBeatWithToken(enrollmentToken: string): Promise { return this.beatsDB.map((beat: any) => omit(beat, ['access_token']))[0]; } - public async removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise { + public async removeTagsFromBeats( + removals: BeatsTagAssignment[] + ): Promise { const beatIds = removals.map(r => r.beatId); const response = this.beatsDB @@ -76,7 +73,9 @@ export class MemoryBeatsAdapter implements CMBeatsAdapter { })); } - public async assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise { + public async assignTagsToBeats( + assignments: BeatsTagAssignment[] + ): Promise { const beatIds = assignments.map(r => r.beatId); this.beatsDB diff --git a/x-pack/plugins/beats_management/public/lib/adapters/beats/rest_beats_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/beats/rest_beats_adapter.ts index 07a81417ebdd8..4a7f768bd4740 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/beats/rest_beats_adapter.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/beats/rest_beats_adapter.ts @@ -5,19 +5,20 @@ */ import { CMBeat } from '../../../../common/domain_types'; -import { RestAPIAdapter } from '../rest_api/adapter_types'; import { - BeatsRemovalReturn, - BeatsTagAssignment, - CMAssignmentReturn, - CMBeatsAdapter, -} from './adapter_types'; + ReturnTypeBulkAction, + ReturnTypeGet, + ReturnTypeList, + ReturnTypeUpdate, +} from '../../../../common/return_types'; +import { RestAPIAdapter } from '../rest_api/adapter_types'; +import { BeatsTagAssignment, CMBeatsAdapter } from './adapter_types'; export class RestBeatsAdapter implements CMBeatsAdapter { constructor(private readonly REST: RestAPIAdapter) {} public async get(id: string): Promise { try { - return await this.REST.get(`/api/beats/agent/${id}`); + return (await this.REST.get>(`/api/beats/agent/${id}`)).item; } catch (e) { return null; } @@ -25,7 +26,9 @@ export class RestBeatsAdapter implements CMBeatsAdapter { public async getBeatWithToken(enrollmentToken: string): Promise { try { - return await this.REST.get(`/api/beats/agent/unknown/${enrollmentToken}`); + return (await this.REST.get>( + `/api/beats/agent/unknown/${enrollmentToken}` + )).item; } catch (e) { return null; } @@ -33,7 +36,8 @@ export class RestBeatsAdapter implements CMBeatsAdapter { public async getAll(ESQuery?: string): Promise { try { - return (await this.REST.get<{ beats: CMBeat[] }>('/api/beats/agents/all', { ESQuery })).beats; + return (await this.REST.get>('/api/beats/agents/all', { ESQuery })) + .list; } catch (e) { return []; } @@ -41,32 +45,30 @@ export class RestBeatsAdapter implements CMBeatsAdapter { public async getBeatsWithTag(tagId: string): Promise { try { - return (await this.REST.get<{ beats: CMBeat[] }>(`/api/beats/agents/tag/${tagId}`)).beats; + return (await this.REST.get>(`/api/beats/agents/tag/${tagId}`)).list; } catch (e) { return []; } } public async update(id: string, beatData: Partial): Promise { - await this.REST.put<{ success: true }>(`/api/beats/agent/${id}`, beatData); + await this.REST.put>(`/api/beats/agent/${id}`, beatData); return true; } - public async removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise { - return (await this.REST.post<{ removals: BeatsRemovalReturn[] }>( - `/api/beats/agents_tags/removals`, - { - removals, - } - )).removals; + public async removeTagsFromBeats( + removals: BeatsTagAssignment[] + ): Promise { + return (await this.REST.post(`/api/beats/agents_tags/removals`, { + removals, + })).results; } - public async assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise { - return (await this.REST.post<{ assignments: CMAssignmentReturn[] }>( - `/api/beats/agents_tags/assignments`, - { - assignments, - } - )).assignments; + public async assignTagsToBeats( + assignments: BeatsTagAssignment[] + ): Promise { + return (await this.REST.post(`/api/beats/agents_tags/assignments`, { + assignments, + })).results; } } diff --git a/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/adapter_types.ts b/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/adapter_types.ts index fb2b077a7532d..e8e2d5cd6b430 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/adapter_types.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/adapter_types.ts @@ -4,19 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ import { ConfigurationBlock } from '../../../../common/domain_types'; +import { ReturnTypeBulkUpsert, ReturnTypeList } from '../../../../common/return_types'; export interface FrontendConfigBlocksAdapter { - upsert( - blocks: ConfigurationBlock[] - ): Promise>; - getForTags( - tagIds: string[], - page: number - ): Promise<{ - error?: string; - blocks: ConfigurationBlock[]; - page: number; - total: number; - }>; + upsert(blocks: ConfigurationBlock[]): Promise; + getForTags(tagIds: string[], page: number): Promise>; delete(id: string): Promise; } diff --git a/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/memory_config_blocks_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/memory_config_blocks_adapter.ts index ab3489ba9745a..b1405cfbf2e60 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/memory_config_blocks_adapter.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/memory_config_blocks_adapter.ts @@ -5,30 +5,26 @@ */ import { ConfigurationBlock } from '../../../../common/domain_types'; +import { ReturnTypeBulkUpsert, ReturnTypeList } from '../../../../common/return_types'; import { FrontendConfigBlocksAdapter } from './adapter_types'; export class MemoryConfigBlocksAdapter implements FrontendConfigBlocksAdapter { constructor(private db: ConfigurationBlock[]) {} - public async upsert(blocks: ConfigurationBlock[]) { + public async upsert(blocks: ConfigurationBlock[]): Promise { this.db = this.db.concat(blocks); - return blocks.map(() => ({ + return { success: true, - blockID: Math.random() - .toString(36) - .substring(7), - })); + results: blocks.map(() => ({ + success: true, + action: 'created', + })), + } as ReturnTypeBulkUpsert; } - public async getForTags( - tagIds: string[] - ): Promise<{ - error?: string; - blocks: ConfigurationBlock[]; - page: number; - total: number; - }> { + public async getForTags(tagIds: string[]): Promise> { return { - blocks: this.db.filter(block => tagIds.includes(block.tag)), + success: true, + list: this.db.filter(block => tagIds.includes(block.tag)), page: 0, total: this.db.filter(block => tagIds.includes(block.tag)).length, }; diff --git a/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/rest_config_blocks_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/rest_config_blocks_adapter.ts index 65fa77cf6a0ad..be501a5e951ba 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/rest_config_blocks_adapter.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/configuration_blocks/rest_config_blocks_adapter.ts @@ -5,6 +5,11 @@ */ import { ConfigurationBlock } from '../../../../common/domain_types'; +import { + ReturnTypeBulkDelete, + ReturnTypeBulkUpsert, + ReturnTypeList, +} from '../../../../common/return_types'; import { RestAPIAdapter } from '../rest_api/adapter_types'; import { FrontendConfigBlocksAdapter } from './adapter_types'; @@ -12,29 +17,19 @@ export class RestConfigBlocksAdapter implements FrontendConfigBlocksAdapter { constructor(private readonly REST: RestAPIAdapter) {} public async upsert(blocks: ConfigurationBlock[]) { - const result = await this.REST.put< - Array<{ success?: boolean; blockID?: string; error?: string }> - >(`/api/beats/configurations`, blocks); + const result = await this.REST.put(`/api/beats/configurations`, blocks); return result; } public async getForTags( tagIds: string[], page: number - ): Promise<{ - error?: string; - blocks: ConfigurationBlock[]; - page: number; - total: number; - }> { - return await this.REST.get<{ - error?: string; - blocks: ConfigurationBlock[]; - page: number; - total: number; - }>(`/api/beats/configurations/${tagIds.join(',')}/${page}`); + ): Promise> { + return await this.REST.get>( + `/api/beats/configurations/${tagIds.join(',')}/${page}` + ); } public async delete(id: string): Promise { - return (await this.REST.delete<{ success: boolean }>(`/api/beats/configurations/${id}`)) + return (await this.REST.delete(`/api/beats/configurations/${id}`)) .success; } } diff --git a/x-pack/plugins/beats_management/public/lib/adapters/tags/rest_tags_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/tags/rest_tags_adapter.ts index 60e4aa11c6ad1..31c55b9272193 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/tags/rest_tags_adapter.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/tags/rest_tags_adapter.ts @@ -6,6 +6,12 @@ import { uniq } from 'lodash'; import { BeatTag, CMBeat } from '../../../../common/domain_types'; +import { + ReturnTypeBulkDelete, + ReturnTypeBulkGet, + ReturnTypeList, + ReturnTypeUpsert, +} from '../../../../common/return_types'; import { RestAPIAdapter } from '../rest_api/adapter_types'; import { CMTagsAdapter } from './adapter_types'; @@ -14,7 +20,9 @@ export class RestTagsAdapter implements CMTagsAdapter { public async getTagsWithIds(tagIds: string[]): Promise { try { - return await this.REST.get(`/api/beats/tags/${uniq(tagIds).join(',')}`); + return (await this.REST.get>( + `/api/beats/tags/${uniq(tagIds).join(',')}` + )).items; } catch (e) { return []; } @@ -22,20 +30,20 @@ export class RestTagsAdapter implements CMTagsAdapter { public async getAll(ESQuery: string): Promise { try { - return await this.REST.get(`/api/beats/tags`, { ESQuery }); + return (await this.REST.get>(`/api/beats/tags`, { ESQuery })).list; } catch (e) { return []; } } public async delete(tagIds: string[]): Promise { - return (await this.REST.delete<{ success: boolean }>( + return (await this.REST.delete( `/api/beats/tags/${uniq(tagIds).join(',')}` )).success; } public async upsertTag(tag: BeatTag): Promise { - const response = await this.REST.put<{ success: boolean }>(`/api/beats/tag/${tag.id}`, { + const response = await this.REST.put>(`/api/beats/tag/${tag.id}`, { color: tag.color, name: tag.name, }); @@ -45,9 +53,9 @@ export class RestTagsAdapter implements CMTagsAdapter { public async getAssignable(beats: CMBeat[]) { try { - return await this.REST.get( + return (await this.REST.get>( `/api/beats/tags/assignable/${beats.map(beat => beat.id).join(',')}` - ); + )).items; } catch (e) { return []; } diff --git a/x-pack/plugins/beats_management/public/lib/adapters/tokens/rest_tokens_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/tokens/rest_tokens_adapter.ts index 78895c8abc73c..8274764e759ab 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/tokens/rest_tokens_adapter.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/tokens/rest_tokens_adapter.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ReturnTypeBulkCreate } from '../../../../common/return_types'; import { RestAPIAdapter } from '../rest_api/adapter_types'; import { CMTokensAdapter } from './adapter_types'; @@ -11,9 +12,12 @@ export class RestTokensAdapter implements CMTokensAdapter { constructor(private readonly REST: RestAPIAdapter) {} public async createEnrollmentTokens(numTokens: number = 1): Promise { - const tokens = (await this.REST.post<{ tokens: string[] }>('/api/beats/enrollment_tokens', { - num_tokens: numTokens, - })).tokens; - return tokens; + const results = (await this.REST.post>( + '/api/beats/enrollment_tokens', + { + num_tokens: numTokens, + } + )).results; + return results.map(result => result.item); } } diff --git a/x-pack/plugins/beats_management/public/lib/beats.ts b/x-pack/plugins/beats_management/public/lib/beats.ts index 01ed52a3d303c..5432a39953b84 100644 --- a/x-pack/plugins/beats_management/public/lib/beats.ts +++ b/x-pack/plugins/beats_management/public/lib/beats.ts @@ -4,13 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ReturnTypeBulkAction } from '../../common/return_types'; import { CMBeat } from './../../common/domain_types'; -import { - BeatsRemovalReturn, - BeatsTagAssignment, - CMAssignmentReturn, - CMBeatsAdapter, -} from './adapters/beats/adapter_types'; +import { BeatsTagAssignment, CMBeatsAdapter } from './adapters/beats/adapter_types'; import { ElasticsearchLib } from './elasticsearch'; export class BeatsLib { @@ -56,14 +52,14 @@ export class BeatsLib { /** unassign tags from beats using an array of tags and beats */ public removeTagsFromBeats = async ( removals: BeatsTagAssignment[] - ): Promise => { + ): Promise => { return await this.adapter.removeTagsFromBeats(removals); }; /** assign tags from beats using an array of tags and beats */ public assignTagsToBeats = async ( assignments: BeatsTagAssignment[] - ): Promise => { + ): Promise => { return await this.adapter.assignTagsToBeats(assignments); }; } diff --git a/x-pack/plugins/beats_management/public/lib/configuration_blocks.ts b/x-pack/plugins/beats_management/public/lib/configuration_blocks.ts index 0dee85e32e63a..c3b21b5df5175 100644 --- a/x-pack/plugins/beats_management/public/lib/configuration_blocks.ts +++ b/x-pack/plugins/beats_management/public/lib/configuration_blocks.ts @@ -23,7 +23,7 @@ export class ConfigBlocksLib { public getForTags = async (tagIds: string[], page: number) => { const result = await this.adapter.getForTags(tagIds, page); - result.blocks = this.jsonConfigToUserYaml(result.blocks); + result.list = this.jsonConfigToUserYaml(result.list); return result; }; diff --git a/x-pack/plugins/beats_management/public/pages/beat/details.tsx b/x-pack/plugins/beats_management/public/pages/beat/details.tsx index b7cffa261c8c4..9b3707b1661f4 100644 --- a/x-pack/plugins/beats_management/public/pages/beat/details.tsx +++ b/x-pack/plugins/beats_management/public/pages/beat/details.tsx @@ -60,7 +60,7 @@ class BeatDetailPageUi extends React.PureComponent { ); this.setState({ - configuration_blocks: blocksResult.blocks, + configuration_blocks: blocksResult.list, tags, }); } diff --git a/x-pack/plugins/beats_management/public/pages/tag/create.tsx b/x-pack/plugins/beats_management/public/pages/tag/create.tsx index 9db3b0adaded7..94b5ac955c165 100644 --- a/x-pack/plugins/beats_management/public/pages/tag/create.tsx +++ b/x-pack/plugins/beats_management/public/pages/tag/create.tsx @@ -61,7 +61,7 @@ class TagCreatePageComponent extends React.PureComponent< ({ ...block, tag: this.state.tag.id })) ); - const creationError = createBlocksResponse.reduce( - (err: string, resp: any) => (!err ? (err = resp.error || '') : err), + const creationError = createBlocksResponse.results.reduce( + (err: string, resp) => (!err ? (err = resp.error ? resp.error.message : '') : err), '' ); if (creationError) { diff --git a/x-pack/plugins/beats_management/public/pages/tag/edit.tsx b/x-pack/plugins/beats_management/public/pages/tag/edit.tsx index 5772c9bd45c0c..401f1d64bca8b 100644 --- a/x-pack/plugins/beats_management/public/pages/tag/edit.tsx +++ b/x-pack/plugins/beats_management/public/pages/tag/edit.tsx @@ -22,7 +22,7 @@ interface TagPageState { beatsTags: BeatTag[]; configuration_blocks: { error?: string | undefined; - blocks: ConfigurationBlock[]; + list: ConfigurationBlock[]; page: number; total: number; }; @@ -47,7 +47,7 @@ class TagEditPageComponent extends React.PureComponent< hasConfigurationBlocksTypes: [], }, configuration_blocks: { - blocks: [], + list: [], page: 0, total: 0, }, @@ -160,7 +160,12 @@ class TagEditPageComponent extends React.PureComponent< const blocksResponse = await this.props.libs.configBlocks.getForTags([this.state.tag.id], page); this.setState({ - configuration_blocks: blocksResponse, + configuration_blocks: blocksResponse as { + error?: string | undefined; + list: ConfigurationBlock[]; + page: number; + total: number; + }, }); }; @@ -189,7 +194,7 @@ class TagEditPageComponent extends React.PureComponent< this.props.goTo(`/overview/configuration_tags`); }; private getNumExclusiveConfigurationBlocks = () => - this.state.configuration_blocks.blocks + this.state.configuration_blocks.list .map(({ type }) => UNIQUENESS_ENFORCING_TYPES.some(uniqueType => uniqueType === type)) .reduce((acc, cur) => (cur ? acc + 1 : acc), 0); } diff --git a/x-pack/plugins/beats_management/public/pages/walkthrough/initial/tag.tsx b/x-pack/plugins/beats_management/public/pages/walkthrough/initial/tag.tsx index 88c6ad844dbce..8dc3afeb06c6b 100644 --- a/x-pack/plugins/beats_management/public/pages/walkthrough/initial/tag.tsx +++ b/x-pack/plugins/beats_management/public/pages/walkthrough/initial/tag.tsx @@ -45,10 +45,7 @@ export class InitialTagPage extends Component { { const createBlocksResponse = await this.props.libs.configBlocks.upsert( this.state.configuration_blocks.map(block => ({ ...block, tag: this.state.tag.id })) ); - const creationError = createBlocksResponse.reduce( - (err: string, resp: any) => (!err ? (err = resp.error || '') : err), + const creationError = createBlocksResponse.results.reduce( + (err: string, resp) => (!err ? (err = resp.error ? resp.error.message : '') : err), '' ); if (creationError) { diff --git a/x-pack/plugins/beats_management/readme.md b/x-pack/plugins/beats_management/readme.md index eb29a9fbf5b51..301caad683dd5 100644 --- a/x-pack/plugins/beats_management/readme.md +++ b/x-pack/plugins/beats_management/readme.md @@ -1,29 +1,32 @@ -# Documentation for Beats CM in x-pack kibana +# Beats CM Notes: Falure to have auth enabled in Kibana will make for a broken UI. UI based errors not yet in place -### Run tests +## Testing -``` -node scripts/jest.js plugins/beats --watch -``` +### Unit tests -and for functional... (from x-pack root) +From `~/kibana/x-pack`, run `node scripts/jest.js plugins/beats --watch`. -``` - node scripts/functional_tests --config test/api_integration/config -``` +### API tests -### Run command to fake an enrolling beat (from beats_management dir) +In one shell, from **~/kibana/x-pack**: +`node scripts/functional_tests-server.js` + +In another shell, from **~kibana/x-pack**: +`node ../scripts/functional_test_runner.js --config test/api_integration/config.js`. + +### Manual e2e testing + +- Run this command to fake an enrolling beat (from beats_management dir) ``` node scripts/enroll.js ``` -### Run a command to setup a fake large-scale deployment - -Note: ts-node is required to be installed gloably from NPM/Yarn for this action +- Run a command to setup a fake large-scale deployment + Note: `ts-node` is required to be installed gloably from NPM/Yarn for this action ``` ts-node scripts/fake_env.ts <# of beats> <# of tags per beat> <# of congifs per tag> diff --git a/x-pack/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts index b031878e9181b..b428e21c1fcc8 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts @@ -168,6 +168,6 @@ export interface FrameworkRouteOptions< export type FrameworkRouteHandler< RouteRequest extends KibanaServerRequest, RouteResponse extends FrameworkResponse -> = (request: FrameworkRequest, h: ResponseToolkit) => void; +> = (request: FrameworkRequest, h: ResponseToolkit) => Promise; export type FrameworkResponse = Lifecycle.ReturnValue; diff --git a/x-pack/plugins/beats_management/server/lib/beats.ts b/x-pack/plugins/beats_management/server/lib/beats.ts index 195117a6a85f2..4f78cc2a294fd 100644 --- a/x-pack/plugins/beats_management/server/lib/beats.ts +++ b/x-pack/plugins/beats_management/server/lib/beats.ts @@ -82,7 +82,6 @@ export class CMBeatsDomain { } const user = typeof userOrToken === 'string' ? this.framework.internalUser : userOrToken; - await this.adapter.update(user, { ...beat, ...beatData, diff --git a/x-pack/plugins/beats_management/server/lib/framework.ts b/x-pack/plugins/beats_management/server/lib/framework.ts index 63da39bb245b6..6dc345f0cc785 100644 --- a/x-pack/plugins/beats_management/server/lib/framework.ts +++ b/x-pack/plugins/beats_management/server/lib/framework.ts @@ -4,14 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import Boom from 'boom'; +import { ResponseObject, ResponseToolkit } from 'hapi'; import { difference } from 'lodash'; +import { BaseReturnType } from '../../common/return_types'; import { BackendFrameworkAdapter, FrameworkRequest, FrameworkResponse, - FrameworkRouteHandler, - FrameworkRouteOptions, } from './adapters/framework/adapter_types'; export class BackendFrameworkLib { @@ -26,13 +25,18 @@ export class BackendFrameworkLib { public registerRoute< RouteRequest extends FrameworkRequest, RouteResponse extends FrameworkResponse - >(route: FrameworkRouteOptions) { + >(route: { + path: string; + method: string | string[]; + licenseRequired?: string[]; + requiredRoles?: string[]; + handler: (request: FrameworkRequest) => Promise; + config?: {}; + }) { this.adapter.registerRoute({ ...route, - handler: this.wrapRouteWithSecurity( - route.handler, - route.licenseRequired || [], - route.requiredRoles + handler: this.wrapErrors( + this.wrapRouteWithSecurity(route.handler, route.licenseRequired || [], route.requiredRoles) ), }); } @@ -71,25 +75,35 @@ export class BackendFrameworkLib { } private wrapRouteWithSecurity( - handler: FrameworkRouteHandler, + handler: (request: FrameworkRequest) => Promise, requiredLicense: string[], requiredRoles?: string[] - ) { - return async (request: FrameworkRequest, h: any) => { + ): (request: FrameworkRequest) => Promise { + return async (request: FrameworkRequest) => { if ( requiredLicense.length > 0 && (this.license.expired || !requiredLicense.includes(this.license.type)) ) { - return Boom.forbidden( - `Your ${ - this.license.type - } license does not support this API or is expired. Please upgrade your license.` - ); + return { + error: { + message: `Your ${ + this.license.type + } license does not support this API or is expired. Please upgrade your license.`, + code: 403, + }, + success: false, + }; } if (requiredRoles) { if (request.user.kind !== 'authenticated') { - return h.response().code(403); + return { + error: { + message: `Request must be authenticated`, + code: 403, + }, + success: false, + }; } if ( @@ -97,10 +111,67 @@ export class BackendFrameworkLib { !request.user.roles.includes('superuser') && difference(requiredRoles, request.user.roles).length !== 0 ) { - return h.response().code(403); + return { + error: { + message: `Request must be authenticated by a user with one of the following user roles: ${requiredRoles.join( + ',' + )}`, + code: 403, + }, + success: false, + }; + } + } + return await handler(request); + }; + } + private wrapErrors( + handler: (request: FrameworkRequest) => Promise + ): (request: FrameworkRequest, h: ResponseToolkit) => Promise { + return async (request: FrameworkRequest, h: ResponseToolkit) => { + try { + const result = await handler(request); + if (!result.error) { + return h.response(result); } + return h + .response({ + error: result.error, + success: false, + }) + .code(result.error.code || 400); + } catch (err) { + let statusCode = err.statusCode; + + // This is the only known non-status code error in the system, but just in case we have an else + if (!statusCode && (err.message as string).includes('Invalid user type')) { + statusCode = 403; + } else { + statusCode = 500; + } + + if (statusCode === 403) { + return h + .response({ + error: { + message: 'Insufficient user permissions for managing Beats configuration', + code: 403, + }, + success: false, + }) + .code(403); + } + + return h + .response({ + error: { + message: err.message, + code: statusCode, + }, + success: false, + }) + .code(statusCode); } - return await handler(request, h); }; } } diff --git a/x-pack/plugins/beats_management/server/rest_api/__tests__/beats_assignments.test.ts b/x-pack/plugins/beats_management/server/rest_api/__tests__/beats_assignments.test.ts index e427c9b0b1115..73a16da179d2f 100644 --- a/x-pack/plugins/beats_management/server/rest_api/__tests__/beats_assignments.test.ts +++ b/x-pack/plugins/beats_management/server/rest_api/__tests__/beats_assignments.test.ts @@ -33,7 +33,7 @@ describe('assign_tags_to_beats', () => { }); expect(statusCode).toEqual(200); - expect(result.assignments).toEqual([{ status: 200, result: 'updated' }]); + expect(result.results).toEqual([{ success: true, result: { message: 'updated' } }]); }); it('should not re-add an existing tag to a beat', async () => { @@ -52,7 +52,7 @@ describe('assign_tags_to_beats', () => { expect(statusCode).toEqual(200); - expect(result.assignments).toEqual([{ status: 200, result: 'updated' }]); + expect(result.results).toEqual([{ success: true, result: { message: 'updated' } }]); let beat; @@ -81,9 +81,9 @@ describe('assign_tags_to_beats', () => { expect(statusCode).toEqual(200); - expect(result.assignments).toEqual([ - { status: 200, result: 'updated' }, - { status: 200, result: 'updated' }, + expect(result.results).toEqual([ + { success: true, result: { message: 'updated' } }, + { success: true, result: { message: 'updated' } }, ]); let beat; @@ -123,9 +123,9 @@ describe('assign_tags_to_beats', () => { expect(statusCode).toEqual(200); - expect(result.assignments).toEqual([ - { status: 200, result: 'updated' }, - { status: 200, result: 'updated' }, + expect(result.results).toEqual([ + { success: true, result: { message: 'updated' } }, + { success: true, result: { message: 'updated' } }, ]); const beat = await serverLibs.beats.getById( diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts b/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts index 39bd54fd0b5e5..aceba95461a79 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts @@ -5,8 +5,9 @@ */ import Joi from 'joi'; import { ConfigurationBlock } from '../../../common/domain_types'; +import { BaseReturnType, ReturnTypeList } from '../../../common/return_types'; +import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; export const createGetBeatConfigurationRoute = (libs: CMServerLibs) => ({ method: 'GET', @@ -19,44 +20,43 @@ export const createGetBeatConfigurationRoute = (libs: CMServerLibs) => ({ }, auth: false, }, - handler: async (request: any, h: any) => { + handler: async ( + request: FrameworkRequest + ): Promise> => { const beatId = request.params.beatId; const accessToken = request.headers['kbn-beats-access-token']; let beat; let configurationBlocks: ConfigurationBlock[]; - try { - beat = await libs.beats.getById(libs.framework.internalUser, beatId); - if (beat === null) { - return h.response({ message: `Beat "${beatId}" not found` }).code(404); - } + beat = await libs.beats.getById(libs.framework.internalUser, beatId); + if (beat === null) { + return { error: { message: `Beat "${beatId}" not found`, code: 404 }, success: false }; + } - const isAccessTokenValid = beat.access_token === accessToken; - if (!isAccessTokenValid) { - return h.response({ message: 'Invalid access token' }).code(401); - } + const isAccessTokenValid = beat.access_token === accessToken; + if (!isAccessTokenValid) { + return { error: { message: 'Invalid access token', code: 401 }, success: false }; + } - await libs.beats.update(libs.framework.internalUser, beat.id, { - last_checkin: new Date(), - }); + await libs.beats.update(libs.framework.internalUser, beat.id, { + last_checkin: new Date(), + }); - if (beat.tags) { - const result = await libs.configurationBlocks.getForTags( - libs.framework.internalUser, - beat.tags, - -1 - ); + if (beat.tags) { + const result = await libs.configurationBlocks.getForTags( + libs.framework.internalUser, + beat.tags, + -1 + ); - configurationBlocks = result.blocks; - } else { - configurationBlocks = []; - } - } catch (err) { - return wrapEsError(err); + configurationBlocks = result.blocks; + } else { + configurationBlocks = []; } return { - configuration_blocks: configurationBlocks, + list: configurationBlocks, + success: true, }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts index 9f3feb4651bd2..df2d7474ccb4a 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts @@ -6,9 +6,10 @@ import Joi from 'joi'; import { omit } from 'lodash'; import { REQUIRED_LICENSES } from '../../../common/constants/security'; +import { CMBeat } from '../../../common/domain_types'; +import { BaseReturnType, ReturnTypeCreate } from '../../../common/return_types'; import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { BeatEnrollmentStatus, CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; // TODO: write to Kibana audit log file https://github.com/elastic/kibana/issues/26024 export const createBeatEnrollmentRoute = (libs: CMServerLibs) => ({ @@ -31,38 +32,38 @@ export const createBeatEnrollmentRoute = (libs: CMServerLibs) => ({ }).required(), }, }, - handler: async (request: FrameworkRequest, h: any) => { + handler: async ( + request: FrameworkRequest + ): Promise> => { const { beatId } = request.params; const enrollmentToken = request.headers['kbn-beats-enrollment-token']; - try { - const { status, accessToken } = await libs.beats.enrollBeat( - enrollmentToken, - beatId, - request.info.remoteAddress, - omit(request.payload, 'enrollment_token') - ); + const { status, accessToken } = await libs.beats.enrollBeat( + enrollmentToken, + beatId, + request.info.remoteAddress, + omit(request.payload, 'enrollment_token') + ); - switch (status) { - case BeatEnrollmentStatus.ExpiredEnrollmentToken: - return h - .response({ - message: BeatEnrollmentStatus.ExpiredEnrollmentToken, - }) - .code(400); - case BeatEnrollmentStatus.InvalidEnrollmentToken: - return h - .response({ - message: BeatEnrollmentStatus.InvalidEnrollmentToken, - }) - .code(400); - case BeatEnrollmentStatus.Success: - default: - return h.response({ access_token: accessToken }).code(201); - } - } catch (err) { - // FIXME move this to kibana route thing in adapter - return wrapEsError(err); + switch (status) { + case BeatEnrollmentStatus.ExpiredEnrollmentToken: + return { + error: { message: BeatEnrollmentStatus.ExpiredEnrollmentToken, code: 400 }, + success: false, + }; + + case BeatEnrollmentStatus.InvalidEnrollmentToken: + return { + error: { message: BeatEnrollmentStatus.InvalidEnrollmentToken, code: 400 }, + success: false, + }; + case BeatEnrollmentStatus.Success: + default: + return { + item: accessToken, + action: 'created', + success: true, + }; } }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/events.ts b/x-pack/plugins/beats_management/server/rest_api/beats/events.ts index ff72f24a630c1..65d7e9979b9ca 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/events.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/events.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ import Joi from 'joi'; +import { BaseReturnType, ReturnTypeBulkAction } from '../../../common/return_types'; +import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; export const beatEventsRoute = (libs: CMServerLibs) => ({ method: 'POST', @@ -18,29 +19,26 @@ export const beatEventsRoute = (libs: CMServerLibs) => ({ }, auth: false, }, - handler: async (request: any, h: any) => { + handler: async (request: FrameworkRequest): Promise => { const beatId = request.params.beatId; const events = request.payload; const accessToken = request.headers['kbn-beats-access-token']; - try { - const beat = await libs.beats.getById(libs.framework.internalUser, beatId); - if (beat === null) { - return h.response({ message: `Beat "${beatId}" not found` }).code(400); - } + const beat = await libs.beats.getById(libs.framework.internalUser, beatId); + if (beat === null) { + return { error: { message: `Beat "${beatId}" not found`, code: 400 }, success: false }; + } - const isAccessTokenValid = beat.access_token === accessToken; - if (!isAccessTokenValid) { - return h.response({ message: 'Invalid access token' }).code(401); - } + const isAccessTokenValid = beat.access_token === accessToken; + if (!isAccessTokenValid) { + return { error: { message: `Invalid access token`, code: 401 }, success: false }; + } - const results = await libs.beatEvents.log(libs.framework.internalUser, beat.id, events); + const results = await libs.beatEvents.log(libs.framework.internalUser, beat.id, events); - return { - response: results, - }; - } catch (err) { - return wrapEsError(err); - } + return { + results, + success: true, + }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/get.ts b/x-pack/plugins/beats_management/server/rest_api/beats/get.ts index 41415521c7bca..874e66bb8a533 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/get.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/get.ts @@ -5,39 +5,35 @@ */ import { CMBeat } from '../../../common/domain_types'; +import { BaseReturnType, ReturnTypeGet } from '../../../common/return_types'; +import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; export const createGetBeatRoute = (libs: CMServerLibs) => ({ method: 'GET', path: '/api/beats/agent/{beatId}/{token?}', requiredRoles: ['beats_admin'], - handler: async (request: any, h: any) => { + handler: async (request: FrameworkRequest): Promise> => { const beatId = request.params.beatId; let beat: CMBeat | null; if (beatId === 'unknown') { - try { - beat = await libs.beats.getByEnrollmentToken(request.user, request.params.token); - if (beat === null) { - return h.response().code(200); - } - } catch (err) { - return wrapEsError(err); + beat = await libs.beats.getByEnrollmentToken(request.user, request.params.token); + if (beat === null) { + return { success: false }; } } else { - try { - beat = await libs.beats.getById(request.user, beatId); - if (beat === null) { - return h.response({ message: 'Beat not found' }).code(404); - } - } catch (err) { - return wrapEsError(err); + beat = await libs.beats.getById(request.user, beatId); + if (beat === null) { + return { error: { message: 'Beat not found', code: 404 }, success: false }; } } delete beat.access_token; - return beat; + return { + item: beat, + success: true, + }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/list.ts b/x-pack/plugins/beats_management/server/rest_api/beats/list.ts index d8f1566607780..74fb98fc877cc 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/list.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/list.ts @@ -7,9 +7,9 @@ import * as Joi from 'joi'; import { REQUIRED_LICENSES } from '../../../common/constants/security'; import { CMBeat } from '../../../common/domain_types'; +import { ReturnTypeList } from '../../../common/return_types'; import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; export const createListAgentsRoute = (libs: CMServerLibs) => ({ method: 'GET', @@ -27,7 +27,7 @@ export const createListAgentsRoute = (libs: CMServerLibs) => ({ ESQuery: Joi.string(), }), }, - handler: async (request: FrameworkRequest) => { + handler: async (request: FrameworkRequest): Promise> => { const listByAndValueParts = request.params.listByAndValue ? request.params.listByAndValue.split('/') : []; @@ -39,27 +39,22 @@ export const createListAgentsRoute = (libs: CMServerLibs) => ({ listByValue = listByAndValueParts[1]; } - try { - let beats: CMBeat[]; + let beats: CMBeat[]; - switch (listBy) { - case 'tag': - beats = await libs.beats.getAllWithTag(request.user, listByValue || ''); - break; + switch (listBy) { + case 'tag': + beats = await libs.beats.getAllWithTag(request.user, listByValue || ''); + break; - default: - beats = await libs.beats.getAll( - request.user, - request.query && request.query.ESQuery ? JSON.parse(request.query.ESQuery) : undefined - ); + default: + beats = await libs.beats.getAll( + request.user, + request.query && request.query.ESQuery ? JSON.parse(request.query.ESQuery) : undefined + ); - break; - } - - return { beats }; - } catch (err) { - // FIXME move this to kibana route thing in adapter - return wrapEsError(err); + break; } + + return { list: beats, success: true, page: -1, total: -1 }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts b/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts index fb2dbb8737e6c..90ba4056d7c98 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts @@ -6,10 +6,10 @@ import Joi from 'joi'; import { REQUIRED_LICENSES } from '../../../common/constants/security'; +import { ReturnTypeBulkAction } from '../../../common/return_types'; import { BeatsTagAssignment } from '../../../public/lib/adapters/beats/adapter_types'; import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; // TODO: write to Kibana audit log file https://github.com/elastic/kibana/issues/26024 export const createTagAssignmentsRoute = (libs: CMServerLibs) => ({ @@ -29,15 +29,29 @@ export const createTagAssignmentsRoute = (libs: CMServerLibs) => ({ }).required(), }, }, - handler: async (request: FrameworkRequest) => { + handler: async (request: FrameworkRequest): Promise => { const { assignments }: { assignments: BeatsTagAssignment[] } = request.payload; - try { - const response = await libs.beats.assignTagsToBeats(request.user, assignments); - return response; - } catch (err) { - // TODO move this to kibana route thing in adapter - return wrapEsError(err); - } + const response = await libs.beats.assignTagsToBeats(request.user, assignments); + + return { + success: true, + results: response.assignments.map(assignment => ({ + success: assignment.status && assignment.status >= 200 && assignment.status < 300, + error: + !assignment.status || assignment.status >= 300 + ? { + code: assignment.status || 400, + message: assignment.result, + } + : undefined, + result: + assignment.status && assignment.status >= 200 && assignment.status < 300 + ? { + message: assignment.result, + } + : undefined, + })), + } as ReturnTypeBulkAction; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts b/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts index e56e114a23204..90c8a78552df7 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts @@ -6,9 +6,9 @@ import Joi from 'joi'; import { REQUIRED_LICENSES } from '../../../common/constants/security'; +import { ReturnTypeBulkAction } from '../../../common/return_types'; import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; // TODO: write to Kibana audit log file https://github.com/elastic/kibana/issues/26024 export const createTagRemovalsRoute = (libs: CMServerLibs) => ({ @@ -28,15 +28,29 @@ export const createTagRemovalsRoute = (libs: CMServerLibs) => ({ }).required(), }, }, - handler: async (request: FrameworkRequest) => { + handler: async (request: FrameworkRequest): Promise => { const { removals } = request.payload; - try { - const response = await libs.beats.removeTagsFromBeats(request.user, removals); - return response; - } catch (err) { - // TODO move this to kibana route thing in adapter - return wrapEsError(err); - } + const response = await libs.beats.removeTagsFromBeats(request.user, removals); + + return { + success: true, + results: response.removals.map(removal => ({ + success: removal.status && removal.status >= 200 && removal.status < 300, + error: + !removal.status || removal.status >= 300 + ? { + code: removal.status || 400, + message: removal.result, + } + : undefined, + result: + removal.status && removal.status >= 200 && removal.status < 300 + ? { + message: removal.result, + } + : undefined, + })), + } as ReturnTypeBulkAction; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/update.ts b/x-pack/plugins/beats_management/server/rest_api/beats/update.ts index 9d415a48f0085..9fef5f1594392 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/update.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/update.ts @@ -5,10 +5,11 @@ */ import Joi from 'joi'; +import { CMBeat } from 'x-pack/plugins/beats_management/common/domain_types'; import { REQUIRED_LICENSES } from '../../../common/constants/security'; -import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; +import { BaseReturnType, ReturnTypeUpdate } from '../../../common/return_types'; +import { FrameworkRequest, internalUser } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; // TODO: write to Kibana audit log file (include who did the verification as well) https://github.com/elastic/kibana/issues/26024 export const createBeatUpdateRoute = (libs: CMServerLibs) => ({ @@ -38,34 +39,54 @@ export const createBeatUpdateRoute = (libs: CMServerLibs) => ({ }), }, }, - handler: async (request: FrameworkRequest, h: any) => { + handler: async ( + request: FrameworkRequest + ): Promise> => { const { beatId } = request.params; const accessToken = request.headers['kbn-beats-access-token']; const remoteAddress = request.info.remoteAddress; const userOrToken = accessToken || request.user; if (request.user.kind === 'unauthenticated' && request.payload.active !== undefined) { - return h - .response({ message: 'access-token is not a valid auth type to change beat status' }) - .code(401); + return { + error: { + message: 'access-token is not a valid auth type to change beat status', + code: 401, + }, + success: false, + }; } - try { - const status = await libs.beats.update(userOrToken, beatId, { - ...request.payload, - host_ip: remoteAddress, - }); + const status = await libs.beats.update(userOrToken, beatId, { + ...request.payload, + host_ip: remoteAddress, + }); - switch (status) { - case 'beat-not-found': - return h.response({ message: 'Beat not found', success: false }).code(404); - case 'invalid-access-token': - return h.response({ message: 'Invalid access token', success: false }).code(401); - } - - return h.response({ success: true }).code(204); - } catch (err) { - return wrapEsError(err); + switch (status) { + case 'beat-not-found': + return { + error: { + message: 'Beat not found', + code: 404, + }, + success: false, + }; + case 'invalid-access-token': + return { + error: { + message: 'Invalid access token', + code: 401, + }, + success: false, + }; } + + const beat = await libs.beats.getById(internalUser, beatId); + + return { + item: beat, + action: 'updated', + success: true, + }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/configurations/delete.ts b/x-pack/plugins/beats_management/server/rest_api/configurations/delete.ts index 31cf998250637..5cd9897be91d0 100644 --- a/x-pack/plugins/beats_management/server/rest_api/configurations/delete.ts +++ b/x-pack/plugins/beats_management/server/rest_api/configurations/delete.ts @@ -5,22 +5,28 @@ */ import { REQUIRED_LICENSES } from '../../../common/constants/security'; +import { ReturnTypeBulkDelete } from '../../../common/return_types'; +import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; export const createDeleteConfidurationsRoute = (libs: CMServerLibs) => ({ method: 'DELETE', path: '/api/beats/configurations/{ids}', requiredRoles: ['beats_admin'], licenseRequired: REQUIRED_LICENSES, - handler: async (request: any) => { + handler: async (request: FrameworkRequest): Promise => { const idString: string = request.params.ids; const ids = idString.split(',').filter((id: string) => id.length > 0); - try { - return await libs.configurationBlocks.delete(request.user, ids); - } catch (err) { - return wrapEsError(err); - } + const results = await libs.configurationBlocks.delete(request.user, ids); + + return { + success: true, + results: results.map(result => ({ + success: result.success, + action: 'deleted', + error: result.success ? undefined : { message: result.reason }, + })), + } as ReturnTypeBulkDelete; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/configurations/get.ts b/x-pack/plugins/beats_management/server/rest_api/configurations/get.ts index 62982cb31eb36..df534f74239ed 100644 --- a/x-pack/plugins/beats_management/server/rest_api/configurations/get.ts +++ b/x-pack/plugins/beats_management/server/rest_api/configurations/get.ts @@ -5,31 +5,27 @@ */ import { REQUIRED_LICENSES } from '../../../common/constants/security'; +import { ConfigurationBlock } from '../../../common/domain_types'; +import { ReturnTypeList } from '../../../common/return_types'; +import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; -import { FrameworkRouteOptions } from './../../lib/adapters/framework/adapter_types'; -export const createGetConfigurationBlocksRoute = (libs: CMServerLibs): FrameworkRouteOptions => ({ +export const createGetConfigurationBlocksRoute = (libs: CMServerLibs) => ({ method: 'GET', path: '/api/beats/configurations/{tagIds}/{page?}', requiredRoles: ['beats_admin'], licenseRequired: REQUIRED_LICENSES, - handler: async (request: any) => { + handler: async (request: FrameworkRequest): Promise> => { const tagIdString: string = request.params.tagIds; const tagIds = tagIdString.split(',').filter((id: string) => id.length > 0); - let tags; - try { - tags = await libs.configurationBlocks.getForTags( - request.user, - tagIds, - parseInt(request.params.page, 10), - 5 - ); - } catch (err) { - return wrapEsError(err); - } + const result = await libs.configurationBlocks.getForTags( + request.user, + tagIds, + parseInt(request.params.page, 10), + 5 + ); - return tags; + return { page: result.page, total: result.total, list: result.blocks, success: true }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/configurations/upsert.ts b/x-pack/plugins/beats_management/server/rest_api/configurations/upsert.ts index 29f9452be2461..67622bbffad56 100644 --- a/x-pack/plugins/beats_management/server/rest_api/configurations/upsert.ts +++ b/x-pack/plugins/beats_management/server/rest_api/configurations/upsert.ts @@ -16,6 +16,7 @@ import { ConfigurationBlock, createConfigurationBlockInterface, } from '../../../common/domain_types'; +import { ReturnTypeBulkUpsert } from '../../../common/return_types'; import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; @@ -30,16 +31,16 @@ export const upsertConfigurationRoute = (libs: CMServerLibs) => ({ payload: Joi.array().items(Joi.object({}).unknown(true)), }, }, - handler: async (request: FrameworkRequest) => { - const result = request.payload.map(async (block: ConfigurationBlock) => { - const assertData = createConfigurationBlockInterface().decode(block); - if (assertData.isLeft()) { - return { - error: `Error parsing block info, ${PathReporter.report(assertData)[0]}`, - }; - } + handler: async (request: FrameworkRequest): Promise => { + const result = await Promise.all( + request.payload.map(async (block: ConfigurationBlock) => { + const assertData = createConfigurationBlockInterface().decode(block); + if (assertData.isLeft()) { + return { + error: `Error parsing block info, ${PathReporter.report(assertData)[0]}`, + }; + } - try { const { blockID, success, error } = await libs.configurationBlocks.save( request.user, block @@ -49,11 +50,16 @@ export const upsertConfigurationRoute = (libs: CMServerLibs) => ({ } return { success, blockID }; - } catch (err) { - return { success: false, error: err.msg }; - } - }); + }) + ); - return Promise.all(result); + return { + results: result.map(r => ({ + success: r.success as boolean, + // TODO: we need to surface this data, not hard coded + action: 'created' as 'created' | 'updated', + })), + success: true, + }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/assignable.ts b/x-pack/plugins/beats_management/server/rest_api/tags/assignable.ts index 544470467b0d1..5cb4d2c445e41 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/assignable.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/assignable.ts @@ -7,29 +7,29 @@ import { flatten } from 'lodash'; import { REQUIRED_LICENSES } from '../../../common/constants/security'; import { BeatTag } from '../../../common/domain_types'; +import { ReturnTypeBulkGet } from '../../../common/return_types'; +import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; export const createAssignableTagsRoute = (libs: CMServerLibs) => ({ method: 'GET', path: '/api/beats/tags/assignable/{beatIds}', requiredRoles: ['beats_admin'], licenseRequired: REQUIRED_LICENSES, - handler: async (request: any) => { + handler: async (request: FrameworkRequest): Promise> => { const beatIdString: string = request.params.beatIds; const beatIds = beatIdString.split(',').filter((id: string) => id.length > 0); let tags: BeatTag[]; - try { - const beats = await libs.beats.getByIds(request.user, beatIds); - tags = await libs.tags.getNonConflictingTags( - request.user, - flatten(beats.map(beat => beat.tags)) - ); - } catch (err) { - return wrapEsError(err); - } + const beats = await libs.beats.getByIds(request.user, beatIds); + tags = await libs.tags.getNonConflictingTags( + request.user, + flatten(beats.map(beat => beat.tags)) + ); - return tags; + return { + items: tags, + success: true, + }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/delete.ts b/x-pack/plugins/beats_management/server/rest_api/tags/delete.ts index a91b98d43ac6f..ab94d31296936 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/delete.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/delete.ts @@ -5,25 +5,28 @@ */ import { REQUIRED_LICENSES } from '../../../common/constants/security'; +import { ReturnTypeBulkDelete } from '../../../common/return_types'; +import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; export const createDeleteTagsWithIdsRoute = (libs: CMServerLibs) => ({ method: 'DELETE', path: '/api/beats/tags/{tagIds}', requiredRoles: ['beats_admin'], licenseRequired: REQUIRED_LICENSES, - handler: async (request: any) => { + handler: async (request: FrameworkRequest): Promise => { const tagIdString: string = request.params.tagIds; const tagIds = tagIdString.split(',').filter((id: string) => id.length > 0); let success: boolean; - try { - success = await libs.tags.delete(request.user, tagIds); - } catch (err) { - return wrapEsError(err); - } + success = await libs.tags.delete(request.user, tagIds); - return { success }; + return { + results: tagIds.map(() => ({ + success, + action: 'deleted', + })), + success, + } as ReturnTypeBulkDelete; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/get.ts b/x-pack/plugins/beats_management/server/rest_api/tags/get.ts index bebda03c565dc..c20c576f4672d 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/get.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/get.ts @@ -6,26 +6,25 @@ import { REQUIRED_LICENSES } from '../../../common/constants/security'; import { BeatTag } from '../../../common/domain_types'; +import { ReturnTypeBulkGet } from '../../../common/return_types'; +import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; -import { FrameworkRouteOptions } from './../../lib/adapters/framework/adapter_types'; -export const createGetTagsWithIdsRoute = (libs: CMServerLibs): FrameworkRouteOptions => ({ +export const createGetTagsWithIdsRoute = (libs: CMServerLibs) => ({ method: 'GET', path: '/api/beats/tags/{tagIds}', requiredRoles: ['beats_admin'], licenseRequired: REQUIRED_LICENSES, - handler: async (request: any) => { + handler: async (request: FrameworkRequest): Promise> => { const tagIdString: string = request.params.tagIds; const tagIds = tagIdString.split(',').filter((id: string) => id.length > 0); let tags: BeatTag[]; - try { - tags = await libs.tags.getWithIds(request.user, tagIds); - } catch (err) { - return wrapEsError(err); - } + tags = await libs.tags.getWithIds(request.user, tagIds); - return tags; + return { + items: tags, + success: true, + }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/list.ts b/x-pack/plugins/beats_management/server/rest_api/tags/list.ts index 2509a230d24dc..749456828a06a 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/list.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/list.ts @@ -5,10 +5,11 @@ */ import * as Joi from 'joi'; +import { ReturnTypeList } from 'x-pack/plugins/beats_management/common/return_types'; import { REQUIRED_LICENSES } from '../../../common/constants/security'; import { BeatTag } from '../../../common/domain_types'; +import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; export const createListTagsRoute = (libs: CMServerLibs) => ({ method: 'GET', @@ -25,17 +26,13 @@ export const createListTagsRoute = (libs: CMServerLibs) => ({ ESQuery: Joi.string(), }), }, - handler: async (request: any) => { + handler: async (request: FrameworkRequest): Promise> => { let tags: BeatTag[]; - try { - tags = await libs.tags.getAll( - request.user, - request.query && request.query.ESQuery ? JSON.parse(request.query.ESQuery) : undefined - ); - } catch (err) { - return wrapEsError(err); - } + tags = await libs.tags.getAll( + request.user, + request.query && request.query.ESQuery ? JSON.parse(request.query.ESQuery) : undefined + ); - return tags; + return { list: tags, success: true, page: -1, total: -1 }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/set.ts b/x-pack/plugins/beats_management/server/rest_api/tags/set.ts index 5c35d478c9014..adf26124b581b 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/set.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/set.ts @@ -6,10 +6,11 @@ import Joi from 'joi'; import { get } from 'lodash'; +import { BeatTag } from 'x-pack/plugins/beats_management/common/domain_types'; import { REQUIRED_LICENSES } from '../../../common/constants'; +import { ReturnTypeUpsert } from '../../../common/return_types'; import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; -import { wrapEsError } from '../../utils/error_wrappers'; // TODO: write to Kibana audit log file export const createSetTagRoute = (libs: CMServerLibs) => ({ @@ -28,7 +29,7 @@ export const createSetTagRoute = (libs: CMServerLibs) => ({ }), }, }, - handler: async (request: FrameworkRequest) => { + handler: async (request: FrameworkRequest): Promise> => { const defaultConfig = { id: request.params.tagId, name: request.params.tagId, @@ -37,13 +38,10 @@ export const createSetTagRoute = (libs: CMServerLibs) => ({ }; const config = { ...defaultConfig, ...get(request, 'payload', {}) }; - try { - const id = await libs.tags.upsertTag(request.user, config); + const id = await libs.tags.upsertTag(request.user, config); + const tag = await libs.tags.getWithIds(request.user, [id]); - return { success: true, id }; - } catch (err) { - // TODO move this to kibana route thing in adapter - return wrapEsError(err); - } + // TODO the action needs to be surfaced + return { success: true, item: tag[0], action: 'created' }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts b/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts index ce3ce504226a7..9de44447a0a01 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import Boom from 'boom'; import Joi from 'joi'; import { get } from 'lodash'; import { REQUIRED_LICENSES } from '../../../common/constants/security'; +import { BaseReturnType, ReturnTypeBulkCreate } from '../../../common/return_types'; import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; import { CMServerLibs } from '../../lib/types'; @@ -28,15 +28,30 @@ export const createTokensRoute = (libs: CMServerLibs) => ({ }).allow(null), }, }, - handler: async (request: FrameworkRequest) => { + handler: async ( + request: FrameworkRequest + ): Promise> => { const numTokens = get(request, 'payload.num_tokens', DEFAULT_NUM_TOKENS); try { const tokens = await libs.tokens.createEnrollmentTokens(request.user, numTokens); - return { tokens }; + return { + results: tokens.map(token => ({ + item: token, + success: true, + action: 'created', + })), + success: true, + }; } catch (err) { libs.framework.log(err.message); - return Boom.internal(); + return { + error: { + message: 'An error occured, please check your Kibana logs', + code: 500, + }, + success: false, + }; } }, }); diff --git a/x-pack/plugins/beats_management/server/utils/error_wrappers/index.ts b/x-pack/plugins/beats_management/server/utils/error_wrappers/index.ts deleted file mode 100644 index 3756b0c74fb10..0000000000000 --- a/x-pack/plugins/beats_management/server/utils/error_wrappers/index.ts +++ /dev/null @@ -1,7 +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. - */ - -export { wrapEsError } from './wrap_es_error'; diff --git a/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.test.ts b/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.test.ts deleted file mode 100644 index e7fb1c2adda21..0000000000000 --- a/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.test.ts +++ /dev/null @@ -1,42 +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 { wrapEsError } from './wrap_es_error'; - -describe('wrap_es_error', () => { - describe('#wrapEsError', () => { - let originalError: any; - beforeEach(() => { - originalError = new Error('I am an error'); - originalError.statusCode = 404; - }); - - it('should return a Boom object', () => { - const wrappedError = wrapEsError(originalError); - - expect(wrappedError.isBoom).toEqual(true); - }); - - it('should return the correct Boom object', () => { - const wrappedError = wrapEsError(originalError); - - expect(wrappedError.output.statusCode).toEqual(originalError.statusCode); - expect(wrappedError.output.payload.message).toEqual(originalError.message); - }); - - it('should return invalid permissions message for 403 errors', () => { - const securityError = new Error('I am an error'); - // @ts-ignore - securityError.statusCode = 403; - const wrappedError = wrapEsError(securityError); - - expect(wrappedError.isBoom).toEqual(true); - expect(wrappedError.message).toEqual( - 'Insufficient user permissions for managing Beats configuration' - ); - }); - }); -}); diff --git a/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.ts b/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.ts deleted file mode 100644 index 16c35fad7d63b..0000000000000 --- a/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.ts +++ /dev/null @@ -1,24 +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. - */ - -// @ts-ignore -import Boom from 'boom'; - -/** - * Wraps ES errors into a Boom error response and returns it - * This also handles the permissions issue gracefully - * - * @param err Object ES error - * @return Object Boom error response - */ -export function wrapEsError(err: any) { - const statusCode = err.statusCode; - if (statusCode === 403) { - return Boom.forbidden('Insufficient user permissions for managing Beats configuration'); - } - - return Boom.boomify(err, { statusCode: err.statusCode }); -} diff --git a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js index 2fa316b4d6476..e407bc75bdc39 100644 --- a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js +++ b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js @@ -28,7 +28,7 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.assignments).to.eql([{ status: 200, result: 'updated' }]); + expect(apiResponse.results).to.eql([{ success: true, result: { message: 'updated' } }]); const esResponse = await es.get({ index: ES_INDEX_NAME, @@ -63,7 +63,7 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.assignments).to.eql([{ status: 200, result: 'updated' }]); + expect(apiResponse.results).to.eql([{ success: true, result: { message: 'updated' } }]); // After adding the existing tag esResponse = await es.get({ @@ -87,9 +87,9 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.assignments).to.eql([ - { status: 200, result: 'updated' }, - { status: 200, result: 'updated' }, + expect(apiResponse.results).to.eql([ + { success: true, result: { message: 'updated' } }, + { success: true, result: { message: 'updated' } }, ]); let esResponse; @@ -126,9 +126,9 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.assignments).to.eql([ - { status: 200, result: 'updated' }, - { status: 200, result: 'updated' }, + expect(apiResponse.results).to.eql([ + { success: true, result: { message: 'updated' } }, + { success: true, result: { message: 'updated' } }, ]); const esResponse = await es.get({ @@ -152,9 +152,9 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.assignments).to.eql([ - { status: 200, result: 'updated' }, - { status: 200, result: 'updated' }, + expect(apiResponse.results).to.eql([ + { success: true, result: { message: 'updated' } }, + { success: true, result: { message: 'updated' } }, ]); let esResponse; @@ -190,8 +190,8 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.assignments).to.eql([ - { status: 404, result: `Beat ${nonExistentBeatId} not found` }, + expect(apiResponse.results).to.eql([ + { success: false, error: { code: 404, message: `Beat ${nonExistentBeatId} not found` } }, ]); }); @@ -206,8 +206,8 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.assignments).to.eql([ - { status: 404, result: `Tag ${nonExistentTag} not found` }, + expect(apiResponse.results).to.eql([ + { success: false, error: { code: 404, message: `Tag ${nonExistentTag} not found` } }, ]); const esResponse = await es.get({ @@ -231,8 +231,14 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.assignments).to.eql([ - { status: 404, result: `Beat ${nonExistentBeatId} and tag ${nonExistentTag} not found` }, + expect(apiResponse.results).to.eql([ + { + success: false, + error: { + code: 404, + message: `Beat ${nonExistentBeatId} and tag ${nonExistentTag} not found`, + }, + }, ]); const esResponse = await es.get({ diff --git a/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js b/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js index 246fc13812a06..6cd4fdf22bb41 100644 --- a/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js +++ b/x-pack/test/api_integration/apis/beats/create_enrollment_tokens.js @@ -20,7 +20,7 @@ export default function ({ getService }) { .send() .expect(200); - const tokensFromApi = apiResponse.tokens; + const tokensFromApi = apiResponse.results.map(r => r.item); const esResponse = await es.search({ index: ES_INDEX_NAME, @@ -44,7 +44,7 @@ export default function ({ getService }) { }) .expect(200); - const tokensFromApi = apiResponse.tokens; + const tokensFromApi = apiResponse.results.map(r => r.item); const esResponse = await es.search({ index: ES_INDEX_NAME, diff --git a/x-pack/test/api_integration/apis/beats/enroll_beat.js b/x-pack/test/api_integration/apis/beats/enroll_beat.js index 395886fc550a6..b94af7215edf7 100644 --- a/x-pack/test/api_integration/apis/beats/enroll_beat.js +++ b/x-pack/test/api_integration/apis/beats/enroll_beat.js @@ -58,7 +58,7 @@ export default function ({ getService }) { .set('kbn-xsrf', 'xxx') .set('kbn-beats-enrollment-token', validEnrollmentToken) .send(beat) - .expect(201); + .expect(200); const esResponse = await es.get({ index: ES_INDEX_NAME, @@ -75,9 +75,9 @@ export default function ({ getService }) { .set('kbn-xsrf', 'xxx') .set('kbn-beats-enrollment-token', validEnrollmentToken) .send(beat) - .expect(201); + .expect(200); - const accessTokenFromApi = apiResponse.access_token; + const accessTokenFromApi = apiResponse.item; const esResponse = await es.get({ index: ES_INDEX_NAME, @@ -98,7 +98,10 @@ export default function ({ getService }) { .send(beat) .expect(400); - expect(apiResponse).to.eql({ message: 'Invalid enrollment token' }); + expect(apiResponse).to.eql({ + success: false, + error: { code: 400, message: 'Invalid enrollment token' }, + }); }); it('should reject an expired enrollment token', async () => { @@ -128,7 +131,10 @@ export default function ({ getService }) { .send(beat) .expect(400); - expect(apiResponse).to.eql({ message: 'Expired enrollment token' }); + expect(apiResponse).to.eql({ + success: false, + error: { code: 400, message: 'Expired enrollment token' }, + }); }); it('should delete the given enrollment token so it may not be reused', async () => { @@ -137,7 +143,7 @@ export default function ({ getService }) { .set('kbn-xsrf', 'xxx') .set('kbn-beats-enrollment-token', validEnrollmentToken) .send(beat) - .expect(201); + .expect(200); const esResponse = await es.get({ index: ES_INDEX_NAME, @@ -154,7 +160,7 @@ export default function ({ getService }) { .set('kbn-xsrf', 'xxx') .set('kbn-beats-enrollment-token', validEnrollmentToken) .send(beat) - .expect(201); + .expect(200); await es.index({ index: ES_INDEX_NAME, @@ -175,7 +181,7 @@ export default function ({ getService }) { .set('kbn-xsrf', 'xxx') .set('kbn-beats-enrollment-token', validEnrollmentToken) .send(beat) - .expect(201); + .expect(200); }); }); } diff --git a/x-pack/test/api_integration/apis/beats/get_beat.js b/x-pack/test/api_integration/apis/beats/get_beat.js index 7d5979fc65ac0..07cc056e3af99 100644 --- a/x-pack/test/api_integration/apis/beats/get_beat.js +++ b/x-pack/test/api_integration/apis/beats/get_beat.js @@ -47,7 +47,7 @@ export default function ({ getService }) { ) .expect(200); - const configurationBlocks = apiResponse.configuration_blocks; + const configurationBlocks = apiResponse.list; expect(configurationBlocks).to.be.an(Array); expect(configurationBlocks.length).to.be(0); @@ -64,7 +64,7 @@ export default function ({ getService }) { ) .expect(200); - const configurationBlocks = apiResponse.configuration_blocks; + const configurationBlocks = apiResponse.list; expect(configurationBlocks).to.be.an(Array); expect(configurationBlocks.length).to.be(3); diff --git a/x-pack/test/api_integration/apis/beats/index.js b/x-pack/test/api_integration/apis/beats/index.js index a6552a383dbd8..da47fdbf77fc7 100644 --- a/x-pack/test/api_integration/apis/beats/index.js +++ b/x-pack/test/api_integration/apis/beats/index.js @@ -10,10 +10,11 @@ export default function ({ getService, loadTestFile }) { const es = getService('es'); describe('beats', () => { - const cleanup = () => es.indices.delete({ - index: ES_INDEX_NAME, - ignore: [404] - }); + const cleanup = () => + es.indices.delete({ + index: ES_INDEX_NAME, + ignore: [404], + }); beforeEach(cleanup); diff --git a/x-pack/test/api_integration/apis/beats/list_beats.js b/x-pack/test/api_integration/apis/beats/list_beats.js index 456ecc318b166..76296f352fb14 100644 --- a/x-pack/test/api_integration/apis/beats/list_beats.js +++ b/x-pack/test/api_integration/apis/beats/list_beats.js @@ -19,7 +19,7 @@ export default function ({ getService }) { it('should return all beats', async () => { const { body: apiResponse } = await supertest.get('/api/beats/agents').expect(200); - const beatsFromApi = apiResponse.beats; + const beatsFromApi = apiResponse.list; expect(beatsFromApi.length).to.be(4); expect(beatsFromApi.filter(beat => beat.hasOwnProperty('verified_on')).length).to.be(1); @@ -29,7 +29,7 @@ export default function ({ getService }) { it('should not return access tokens', async () => { const { body: apiResponse } = await supertest.get('/api/beats/agents').expect(200); - const beatsFromApi = apiResponse.beats; + const beatsFromApi = apiResponse.list; expect(beatsFromApi.length).to.be(4); expect(beatsFromApi.filter(beat => beat.hasOwnProperty('access_token')).length).to.be(0); diff --git a/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js b/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js index fc55ee9d9da29..3e7c6ce8f48ff 100644 --- a/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js +++ b/x-pack/test/api_integration/apis/beats/remove_tags_from_beats.js @@ -28,7 +28,7 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.removals).to.eql([{ status: 200, result: 'updated' }]); + expect(apiResponse.results).to.eql([{ success: true, result: { message: 'updated' } }]); const esResponse = await es.get({ index: ES_INDEX_NAME, @@ -48,9 +48,9 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.removals).to.eql([ - { status: 200, result: 'updated' }, - { status: 200, result: 'updated' }, + expect(apiResponse.results).to.eql([ + { success: true, result: { message: 'updated' } }, + { success: true, result: { message: 'updated' } }, ]); let esResponse; @@ -84,9 +84,9 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.removals).to.eql([ - { status: 200, result: 'updated' }, - { status: 200, result: 'updated' }, + expect(apiResponse.results).to.eql([ + { success: true, result: { message: 'updated' } }, + { success: true, result: { message: 'updated' } }, ]); const esResponse = await es.get({ @@ -107,9 +107,9 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.removals).to.eql([ - { status: 200, result: 'updated' }, - { status: 200, result: 'updated' }, + expect(apiResponse.results).to.eql([ + { success: true, result: { message: 'updated' } }, + { success: true, result: { message: 'updated' } }, ]); let esResponse; @@ -145,8 +145,8 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.removals).to.eql([ - { status: 404, result: `Beat ${nonExistentBeatId} not found` }, + expect(apiResponse.results).to.eql([ + { success: false, error: { code: 404, message: `Beat ${nonExistentBeatId} not found` } }, ]); }); @@ -161,8 +161,8 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.removals).to.eql([ - { status: 404, result: `Tag ${nonExistentTag} not found` }, + expect(apiResponse.results).to.eql([ + { success: false, error: { code: 404, message: `Tag ${nonExistentTag} not found` } }, ]); const esResponse = await es.get({ @@ -186,8 +186,14 @@ export default function ({ getService }) { }) .expect(200); - expect(apiResponse.removals).to.eql([ - { status: 404, result: `Beat ${nonExistentBeatId} and tag ${nonExistentTag} not found` }, + expect(apiResponse.results).to.eql([ + { + success: false, + error: { + code: 404, + message: `Beat ${nonExistentBeatId} and tag ${nonExistentTag} not found`, + }, + }, ]); const esResponse = await es.get({ diff --git a/x-pack/test/api_integration/apis/beats/set_config.js b/x-pack/test/api_integration/apis/beats/set_config.js index 53fa2b0133ee4..a4d7d491d4778 100644 --- a/x-pack/test/api_integration/apis/beats/set_config.js +++ b/x-pack/test/api_integration/apis/beats/set_config.js @@ -31,7 +31,7 @@ export default function ({ getService }) { config: { elasticsearch: { hosts: ['localhost:9200'], username: 'foo' } }, }, ]) - .expect(201); + .expect(200); const esResponse = await es.get({ index: ES_INDEX_NAME, id: `tag:${tagId}`, diff --git a/x-pack/test/api_integration/apis/beats/update_beat.js b/x-pack/test/api_integration/apis/beats/update_beat.js index e700414d45b05..090668aff925c 100644 --- a/x-pack/test/api_integration/apis/beats/update_beat.js +++ b/x-pack/test/api_integration/apis/beats/update_beat.js @@ -25,6 +25,7 @@ export default function ({ getService }) { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.' + 'eyJjcmVhdGVkIjoiMjAxOC0wNi0zMFQwMzo0MjoxNS4yMzBaIiwiaWF0IjoxNTMwMzMwMTM1fQ.' + 'SSsX2Byyo1B1bGxV8C3G4QldhE5iH87EY_1r21-bwbI'; + const version = chance.integer({ min: 1, max: 10 }) + '.' + @@ -62,9 +63,14 @@ export default function ({ getService }) { await supertest .put(`/api/beats/agent/${beatId}`) .set('kbn-xsrf', 'xxx') - .set('kbn-beats-access-token', validEnrollmentToken) + .set( + 'kbn-beats-access-token', + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.' + + 'eyJjcmVhdGVkIjoiMjAxOC0wNi0zMFQwMzo0MjoxNS4yMzBaIiwiaWF0IjoxNTMwMzMwMTM1fQ.' + + 'SSsX2Byyo1B1bGxV8C3G4QldhE5iH87EY_1r21-bwbI' + ) .send(beat) - .expect(204); + .expect(200); const beatInEs = await es.get({ index: ES_INDEX_NAME, @@ -88,7 +94,7 @@ export default function ({ getService }) { .send(beat) .expect(401); - expect(body.message).to.be('Invalid access token'); + expect(body.error.message).to.be('Invalid access token'); const beatInEs = await es.get({ index: ES_INDEX_NAME, @@ -111,7 +117,7 @@ export default function ({ getService }) { .send(beat) .expect(404); - expect(body.message).to.be('Beat not found'); + expect(body.error.message).to.be('Beat not found'); }); }); } From bbb21b1c854c1b141ec3267fc9b34a820e4aa754 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Thu, 28 Mar 2019 14:57:14 -0400 Subject: [PATCH 91/96] [Monitoring] Address shard allocation color mismatch (#34086) * Address mismatch and add a couple starter tests * More tests and fixing a bug --- .../__snapshots__/shard.test.js.snap | 109 ++++++++++++++++++ .../shard_allocation/components/shard.js | 43 ++++--- .../shard_allocation/components/shard.test.js | 107 +++++++++++++++++ 3 files changed, 242 insertions(+), 17 deletions(-) create mode 100644 x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/__snapshots__/shard.test.js.snap create mode 100644 x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.test.js diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/__snapshots__/shard.test.js.snap b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/__snapshots__/shard.test.js.snap new file mode 100644 index 0000000000000..2a43104005c79 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/__snapshots__/shard.test.js.snap @@ -0,0 +1,109 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Shard should show for assigned primary shards 1`] = ` +
    + + 0 + +
    +`; + +exports[`Shard should show for assigned replica shards 1`] = ` +
    + + 0 + +
    +`; + +exports[`Shard should show for initializing shards 1`] = ` +
    + + 0 + +
    +`; + +exports[`Shard should show for relocating shards 1`] = ` +
    + + 0 + +
    +`; + +exports[`Shard should show unassigned primary shards 1`] = ` +
    + + 0 + +
    +`; + +exports[`Shard should show unassigned replica shards 1`] = ` +
    + + 0 + +
    +`; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js index b5033e625ba60..7e1b240d5717b 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js @@ -13,25 +13,34 @@ import { i18n } from '@kbn/i18n'; import { EuiToolTip, EuiBadge } from '@elastic/eui'; function getColor(classes) { - return classes.split(' ').reduce((color, cls) => { - if (color) { - return color; - } + const classList = classes.split(' '); + + if (classList.includes('emergency')) { + return 'danger'; + } - switch (cls) { - case 'primary': - return 'hollow'; - case 'replica': - return 'secondary'; - case 'relocation': - return 'accent'; - case 'initializing': - return 'default'; - case 'emergency': - case 'unassigned': - return 'danger'; + if (classList.includes('unassigned')) { + if (classList.includes('replica')) { + return 'warning'; } - }, null); + return 'danger'; + } + + if (classList.includes('relocating')) { + return 'accent'; + } + + if (classList.includes('initializing')) { + return 'default'; + } + + if (classList.includes('primary')) { + return 'primary'; + } + + if (classList.includes('replica')) { + return 'secondary'; + } } export class Shard extends React.Component { diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.test.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.test.js new file mode 100644 index 0000000000000..4239b1846b8f8 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.test.js @@ -0,0 +1,107 @@ +/* + * 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 { shallow } from 'enzyme'; +import { Shard } from './shard'; + +describe('Shard', () => { + it('should show unassigned primary shards', () => { + const props = { + shard: { + state: 'UNASSIGNED', + primary: true, + shard: 0, + tooltip_message: 'Unassigned', + type: 'shard', + master: true + } + }; + + const component = shallow(); + expect(component).toMatchSnapshot(); + }); + + it('should show unassigned replica shards', () => { + const props = { + shard: { + state: 'UNASSIGNED', + primary: false, + shard: 0, + tooltip_message: 'Unassigned', + type: 'shard', + master: false + } + }; + + const component = shallow(); + expect(component).toMatchSnapshot(); + }); + + it('should show for assigned primary shards', () => { + const props = { + shard: { + state: 'STARTED', + primary: true, + shard: 0, + tooltip_message: 'Started', + type: 'shard', + master: true + } + }; + + const component = shallow(); + expect(component).toMatchSnapshot(); + }); + + it('should show for assigned replica shards', () => { + const props = { + shard: { + state: 'STARTED', + primary: false, + shard: 0, + tooltip_message: 'Started', + type: 'shard', + master: true + } + }; + + const component = shallow(); + expect(component).toMatchSnapshot(); + }); + + it('should show for relocating shards', () => { + const props = { + shard: { + state: 'RELOCATING', + primary: true, + shard: 0, + tooltip_message: 'Relocating', + type: 'shard', + master: true + } + }; + + const component = shallow(); + expect(component).toMatchSnapshot(); + }); + + it('should show for initializing shards', () => { + const props = { + shard: { + state: 'INITIALIZING', + primary: true, + shard: 0, + tooltip_message: 'Initializing', + type: 'shard', + master: true + } + }; + + const component = shallow(); + expect(component).toMatchSnapshot(); + }); +}); From d2c077ae59ac2f9c996edb1ebd12385a4f29f3fa Mon Sep 17 00:00:00 2001 From: "dave.snider@gmail.com" Date: Thu, 28 Mar 2019 12:27:35 -0700 Subject: [PATCH 92/96] eui 9.7.1 (#34098) --- package.json | 2 +- .../plugins/kbn_tp_run_pipeline/package.json | 2 +- .../plugins/kbn_tp_custom_visualizations/package.json | 2 +- .../plugins/kbn_tp_sample_panel_action/package.json | 2 +- .../plugins/kbn_tp_visualize_embedding/package.json | 2 +- x-pack/package.json | 2 +- yarn.lock | 8 ++++---- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 20c260c35596e..7d2906ace0021 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "@babel/polyfill": "^7.2.5", "@babel/register": "^7.0.0", "@elastic/datemath": "5.0.2", - "@elastic/eui": "9.7.0", + "@elastic/eui": "9.7.1", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.3.2", diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json index 3135a040cec92..ce2d0111c50bb 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.7.0", + "@elastic/eui": "9.7.1", "react": "^16.8.0", "react-dom": "^16.8.0" } diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json index cf922f28b944a..d1491583bc0d5 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.7.0", + "@elastic/eui": "9.7.1", "react": "^16.8.0" } } diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json index c7148b8ce38f8..dad6a74d14362 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.7.0", + "@elastic/eui": "9.7.1", "react": "^16.8.0" }, "scripts": { diff --git a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json b/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json index e2a14cf36f71e..9051a0e79c857 100644 --- a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json +++ b/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.7.0", + "@elastic/eui": "9.7.1", "react": "^16.8.0", "react-dom": "^16.8.0" } diff --git a/x-pack/package.json b/x-pack/package.json index 60f4f85122c84..f79e9eeaf5658 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -142,7 +142,7 @@ "@babel/register": "^7.0.0", "@babel/runtime": "^7.3.4", "@elastic/datemath": "5.0.2", - "@elastic/eui": "9.7.0", + "@elastic/eui": "9.7.1", "@elastic/node-crypto": "0.1.2", "@elastic/numeral": "2.3.2", "@kbn/babel-preset": "1.0.0", diff --git a/yarn.lock b/yarn.lock index 4bd503343a588..ca116a43bfc9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -841,10 +841,10 @@ tabbable "^1.1.0" uuid "^3.1.0" -"@elastic/eui@9.7.0": - version "9.7.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-9.7.0.tgz#6da25d665936fba713d24bfec3beba8c20a4272b" - integrity sha512-2cXEvAxYEfS1i5ZwhSl63rGT6jMQOQHed4RLFnuf0xmZyUjIO9he8EVY9YAH2eFfrRvEVggQltLLEI+JXhiqSA== +"@elastic/eui@9.7.1": + version "9.7.1" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-9.7.1.tgz#817b5018303a2c6160011e201a8d21fca2f3e47b" + integrity sha512-yYTnW1jqv586M8dD4TxTa/9wkj84gJuHeDh9F13z7XGeZ/clUN0XP43Y5Jzv80Q3M80VlEuTpABYMGpPqBAw8w== dependencies: "@types/lodash" "^4.14.116" "@types/numeral" "^0.0.25" From 980d736c047c54dd03c1c992dabff69ebbd5a97b Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 28 Mar 2019 12:36:48 -0700 Subject: [PATCH 93/96] disable flaky test --- x-pack/test/api_integration/apis/management/rollup/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/management/rollup/index.js b/x-pack/test/api_integration/apis/management/rollup/index.js index 3c55ce6a7a705..45d84ddc6ad5d 100644 --- a/x-pack/test/api_integration/apis/management/rollup/index.js +++ b/x-pack/test/api_integration/apis/management/rollup/index.js @@ -5,7 +5,8 @@ */ export default function ({ loadTestFile }) { - describe('rollup', () => { + // FLAKY: https://github.com/elastic/kibana/issues/33282 + describe.skip('rollup', () => { loadTestFile(require.resolve('./rollup')); loadTestFile(require.resolve('./index_patterns_extensions')); loadTestFile(require.resolve('./rollup_search')); From 5f511fcd83067eb865a5d6c77db300e0d84397bc Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Thu, 28 Mar 2019 20:53:07 +0100 Subject: [PATCH 94/96] Remove ui/jquery (#33855) --- .../__tests__/nested_fancy_forms.js | 13 +-- .../jquery/__tests__/find_test_subject.js | 88 ------------------- .../ui/public/jquery/find_test_subject.js | 77 ---------------- .../modals/__tests__/confirm_modal_promise.js | 9 +- .../ui/public/test_harness/test_harness.js | 4 - 5 files changed, 12 insertions(+), 179 deletions(-) delete mode 100644 src/legacy/ui/public/jquery/__tests__/find_test_subject.js delete mode 100644 src/legacy/ui/public/jquery/find_test_subject.js diff --git a/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js b/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js index 1d8cda79d10f0..095007004ae7f 100644 --- a/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js +++ b/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js @@ -19,6 +19,7 @@ import ngMock from 'ng_mock'; import expect from '@kbn/expect'; +import testSubjSelector from '@kbn/test-subj-selector'; import sinon from 'sinon'; import $ from 'jquery'; @@ -85,7 +86,7 @@ describe('fancy forms', function () { expect($scope.person.errorCount()).to.be(1); expect($scope.person.softErrorCount()).to.be(0); - $el.findTestSubject('submit').click(); + $el.find(testSubjSelector('submit')).click(); expect($scope.person.errorCount()).to.be(1); expect($scope.person.softErrorCount()).to.be(1); }); @@ -96,7 +97,7 @@ describe('fancy forms', function () { expect($scope.person.errorCount()).to.be(1); sinon.assert.notCalled(onSubmit); - $el.findTestSubject('submit').click(); + $el.find(testSubjSelector('submit')).click(); expect($scope.person.errorCount()).to.be(1); sinon.assert.notCalled(onSubmit); @@ -106,7 +107,7 @@ describe('fancy forms', function () { expect($scope.person.errorCount()).to.be(0); sinon.assert.notCalled(onSubmit); - $el.findTestSubject('submit').click(); + $el.find(testSubjSelector('submit')).click(); expect($scope.person.errorCount()).to.be(0); sinon.assert.calledOnce(onSubmit); }); @@ -114,7 +115,7 @@ describe('fancy forms', function () { it('new fields are no longer soft after blur', function () { const { $scope, $el } = setup({ name: '' }); expect($scope.person.softErrorCount()).to.be(0); - $el.findTestSubject('name').blur(); + $el.find(testSubjSelector('name')).blur(); expect($scope.person.softErrorCount()).to.be(1); }); @@ -139,7 +140,7 @@ describe('fancy forms', function () { expect($scope.person.errorCount()).to.be(2); expect($scope.person.softErrorCount()).to.be(0); - $el.findTestSubject('taskDesc').first().blur(); + $el.find(testSubjSelector('taskDesc')).first().blur(); expect($scope.person.errorCount()).to.be(2); expect($scope.person.softErrorCount()).to.be(1); @@ -177,7 +178,7 @@ describe('fancy forms', function () { expect(form.softErrorCount()).to.be(0); // blurs only count locally - $task.findTestSubject('taskDesc').blur(); + $task.find(testSubjSelector('taskDesc')).blur(); expect(form.softErrorCount()).to.be(1); // but parent form see them diff --git a/src/legacy/ui/public/jquery/__tests__/find_test_subject.js b/src/legacy/ui/public/jquery/__tests__/find_test_subject.js deleted file mode 100644 index 6fc781fcabc5d..0000000000000 --- a/src/legacy/ui/public/jquery/__tests__/find_test_subject.js +++ /dev/null @@ -1,88 +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 expect from '@kbn/expect'; -import $ from 'jquery'; - -function $make(subject) { - return $('
    ').attr('data-test-subj', subject); -} - -describe('jQuery.findTestSubject', function () { - it('finds all of the element with a subject', function () { - const $container = $('
    '); - const $match = $make('subject').appendTo($container); - const $noMatch = $make('notSubject').appendTo($container); - - const $found = $container.findTestSubject('subject'); - expect($found.is($match)).to.be(true); - expect($found.is($noMatch)).to.be(false); - }); - - it('finds multiple elements with a subject', function () { - const $container = $('
    '); - const $match = $make('subject').appendTo($container); - const $otherMatch = $make('subject').appendTo($container); - - const $found = $container.findTestSubject('subject'); - expect($found.filter($match).length).to.be(1); - expect($found.filter($otherMatch).length).to.be(1); - }); - - it('finds all of the elements with either subject', function () { - const $container = $('
    '); - const $match1 = $make('subject').appendTo($container); - const $match2 = $make('alsoSubject').appendTo($container); - const $noMatch = $make('notSubject').appendTo($container); - - const $found = $container.findTestSubject('subject', 'alsoSubject'); - expect($found.filter($match1).length).to.be(1); - expect($found.filter($match2).length).to.be(1); - expect($found.filter($noMatch).length).to.be(0); - }); - - it('finds all of the elements with a descendant selector', function () { - const $container = $('
    '); - const $parent = $make('foo name').appendTo($container); - const $bar = $make('bar othername').appendTo($parent); - const $baz = $make('baz third name').appendTo($parent); - - expect($container.findTestSubject('foo bar').is($bar)).to.be(true); - expect($container.findTestSubject('foo bar').is($baz)).to.be(false); - - expect($container.findTestSubject('foo baz').is($bar)).to.be(false); - expect($container.findTestSubject('foo baz').is($baz)).to.be(true); - }); - - it('finds elements with compound subjects', function () { - const $container = $('
    '); - const $bar = $make('button bar').appendTo($container); - const $baz = $make('button baz').appendTo($container); - - expect($container.findTestSubject('button&bar').is($bar)).to.be(true); - expect($container.findTestSubject('button& bar').is($bar)).to.be(true); - expect($container.findTestSubject('button & bar').is($bar)).to.be(true); - expect($container.findTestSubject('button &bar').is($bar)).to.be(true); - - expect($container.findTestSubject('button&baz').is($baz)).to.be(true); - expect($container.findTestSubject('button& baz').is($baz)).to.be(true); - expect($container.findTestSubject('button & baz').is($baz)).to.be(true); - expect($container.findTestSubject('button &baz').is($baz)).to.be(true); - }); -}); diff --git a/src/legacy/ui/public/jquery/find_test_subject.js b/src/legacy/ui/public/jquery/find_test_subject.js deleted file mode 100644 index e30b78a121cdc..0000000000000 --- a/src/legacy/ui/public/jquery/find_test_subject.js +++ /dev/null @@ -1,77 +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 testSubjSelector from '@kbn/test-subj-selector'; - -// eslint-disable-next-line @kbn/eslint/no-default-export -export default function bindToJquery($) { - - /** - * Find elements with the `data-test-subj` attribute by the terms in that attribute. - * - * ```js - * // this - * let $button = $('[data-test-subj~="saveButton"]'); - * - * // becomes this - * let $button = $.findTestSubject('saveButton'); - * ``` - * - * Supports multiple subjects - * ```js - * // find any saveButton or cancelButton - * let $buttons = $.findTestSubject('saveButton', 'cancelButton'); - * ``` - * - * Supports subject "selectors" - * ```js - * // find any saveButton inside a savedObjectForm - * let $button = $.findTestSubject('savedObjectForm saveButton'); - * ``` - * - * Supports selecting compound subjects - * ```js - * // find any smallButton that is also a saveButton inside a savedObjectForm - * let $input = $.findTestSubject('savedObjectForm smallButton&saveButton'); - * ``` - * - * @return {jQueryCollection} - */ - $.findTestSubject = function () { - return findTestSubject.apply($(document.body), arguments); - }; - - /** - * Just like $.findTestSubject, except only finds elements within another element. - * @return {jQueryCollection} - */ - $.fn.findTestSubject = findTestSubject; - - function findTestSubject(...subjectSelectors) { - let $els = $(); - const $context = this; - - subjectSelectors.forEach(function (selector) { - $els = $els.add($context.find(testSubjSelector(selector))); - }); - - return $els; - } - -} diff --git a/src/legacy/ui/public/modals/__tests__/confirm_modal_promise.js b/src/legacy/ui/public/modals/__tests__/confirm_modal_promise.js index f5fabfd5e93a5..76b730e5b2708 100644 --- a/src/legacy/ui/public/modals/__tests__/confirm_modal_promise.js +++ b/src/legacy/ui/public/modals/__tests__/confirm_modal_promise.js @@ -18,6 +18,7 @@ */ import expect from '@kbn/expect'; +import testSubjSelector from '@kbn/test-subj-selector'; import ngMock from 'ng_mock'; import sinon from 'sinon'; import $ from 'jquery'; @@ -43,7 +44,7 @@ describe('ui/modals/confirm_modal_promise', function () { afterEach(function () { $rootScope.$digest(); - $.findTestSubject('confirmModalConfirmButton').click(); + $(testSubjSelector('confirmModalConfirmButton')).click(); }); describe('before timeout completes', function () { @@ -58,7 +59,7 @@ describe('ui/modals/confirm_modal_promise', function () { describe('after timeout completes', function () { it('confirmation dialogue is loaded to dom with message', function () { $rootScope.$digest(); - const confirmModalElement = $.findTestSubject('confirmModal'); + const confirmModalElement = $(testSubjSelector('confirmModal')); expect(confirmModalElement).to.not.be(undefined); const htmlString = confirmModalElement[0].innerHTML; @@ -73,7 +74,7 @@ describe('ui/modals/confirm_modal_promise', function () { promise.then(confirmCallback, cancelCallback); $rootScope.$digest(); - const confirmButton = $.findTestSubject('confirmModalConfirmButton'); + const confirmButton = $(testSubjSelector('confirmModalConfirmButton')); confirmButton.click(); expect(confirmCallback.called).to.be(true); @@ -88,7 +89,7 @@ describe('ui/modals/confirm_modal_promise', function () { promise.then(confirmCallback, cancelCallback); $rootScope.$digest(); - const noButton = $.findTestSubject('confirmModalCancelButton'); + const noButton = $(testSubjSelector('confirmModalCancelButton')); noButton.click(); expect(cancelCallback.called).to.be(true); diff --git a/src/legacy/ui/public/test_harness/test_harness.js b/src/legacy/ui/public/test_harness/test_harness.js index 36dc38b1c3b82..178971c582d66 100644 --- a/src/legacy/ui/public/test_harness/test_harness.js +++ b/src/legacy/ui/public/test_harness/test_harness.js @@ -18,8 +18,6 @@ */ // chrome expects to be loaded first, let it get its way -import $ from 'jquery'; -import bindJqueryToFindTestSubject from 'ui/jquery/find_test_subject'; import chrome from '../chrome'; import { parse as parseUrl } from 'url'; @@ -32,8 +30,6 @@ import './test_harness.css'; import 'ng_mock'; import { setupTestSharding } from './test_sharding'; -bindJqueryToFindTestSubject($); - const { query } = parseUrl(window.location.href, true); if (query && query.mocha) { try { From fd3535fdcf7ce337e4266b36014d0c5b10d6ebae Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Thu, 28 Mar 2019 12:56:36 -0700 Subject: [PATCH 95/96] Remove dangerously set inner html (#33976) Fixes #24781 Replaces dangerouslySetInnerHtml with JSX using FormattedMessage for i18n. --- .../suggestion_component.test.tsx.snap | 18 +-- .../typeahead/suggestion_component.tsx | 9 +- .../shared/KueryBar/Typeahead/Suggestion.js | 4 +- .../autocomplete_field/suggestion_item.tsx | 4 +- .../autocomplete_field/suggestion_item.tsx | 4 +- .../__tests__/conjunction.js | 7 +- .../autocomplete_providers/__tests__/field.js | 2 +- .../__tests__/operator.js | 2 +- .../autocomplete_providers/conjunction.js | 63 +++++--- .../public/autocomplete_providers/field.js | 21 +-- .../public/autocomplete_providers/operator.js | 150 ++++++++++-------- .../__snapshots__/suggestion.test.js.snap | 10 +- .../kql_filter_bar/suggestion/suggestion.js | 4 +- 13 files changed, 156 insertions(+), 142 deletions(-) diff --git a/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestion_component.test.tsx.snap b/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestion_component.test.tsx.snap index 56875f1f1c3f1..92ca296ed8058 100644 --- a/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestion_component.test.tsx.snap +++ b/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestion_component.test.tsx.snap @@ -26,12 +26,9 @@ exports[`SuggestionComponent Should display the suggestion and use the provided
    + > + This is not a helpful suggestion +
    `; @@ -62,12 +59,9 @@ exports[`SuggestionComponent Should make the element active if the selected prop
    + > + This is not a helpful suggestion +
    `; diff --git a/src/legacy/ui/public/query_bar/components/typeahead/suggestion_component.tsx b/src/legacy/ui/public/query_bar/components/typeahead/suggestion_component.tsx index 00ffc5e835c24..8000585e98183 100644 --- a/src/legacy/ui/public/query_bar/components/typeahead/suggestion_component.tsx +++ b/src/legacy/ui/public/query_bar/components/typeahead/suggestion_component.tsx @@ -67,14 +67,7 @@ export const SuggestionComponent: SFC = props => {
    {props.suggestion.text}
    -
    +
    {props.suggestion.description}
    ); diff --git a/x-pack/plugins/apm/public/components/shared/KueryBar/Typeahead/Suggestion.js b/x-pack/plugins/apm/public/components/shared/KueryBar/Typeahead/Suggestion.js index 618d9db44fa5c..e7c5564851efa 100644 --- a/x-pack/plugins/apm/public/components/shared/KueryBar/Typeahead/Suggestion.js +++ b/x-pack/plugins/apm/public/components/shared/KueryBar/Typeahead/Suggestion.js @@ -113,9 +113,7 @@ function Suggestion(props) { {props.suggestion.text} - + {props.suggestion.description} ); } diff --git a/x-pack/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx b/x-pack/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx index 2ab04b4d87157..2b0537e11af92 100644 --- a/x-pack/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx +++ b/x-pack/plugins/beats_management/public/components/autocomplete_field/suggestion_item.tsx @@ -36,9 +36,7 @@ export class SuggestionItem extends React.Component { {suggestion.text} - + {suggestion.description} ); } diff --git a/x-pack/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx b/x-pack/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx index 69c02e1c7f7d7..b6f2aae12bddf 100644 --- a/x-pack/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx +++ b/x-pack/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx @@ -36,9 +36,7 @@ export class SuggestionItem extends React.Component { {suggestion.text} - + {suggestion.description} ); } diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js index e24b7e455e04d..17518ffa488c0 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js @@ -35,13 +35,14 @@ describe('Kuery conjunction suggestions', function () { expect(suggestions.map(suggestion => suggestion.start)).to.eql([end, end]); expect(suggestions.map(suggestion => suggestion.end)).to.eql([end, end]); }); - it('should have descriptions', function () { const text = ' '; const suggestions = getSuggestions({ text }); - expect(suggestions.length).to.be(2); + expect(typeof suggestions).to.be('object'); + expect(Object.keys(suggestions).length).to.be(2); suggestions.forEach(suggestion => { - expect(suggestion.description.length).to.be.greaterThan(0); + expect(typeof suggestion).to.be('object'); + expect(suggestion).to.have.property('description'); }); }); }); diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js index f95615ae40c2e..de908491eee6a 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js @@ -77,7 +77,7 @@ describe('Kuery field suggestions', function () { const suggestions = getSuggestions({ prefix, suffix }); expect(suggestions.length).to.be.greaterThan(0); suggestions.forEach(suggestion => { - expect(suggestion.description.length).to.be.greaterThan(0); + expect(suggestion).to.have.property('description'); }); }); }); diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js index d56601c997f81..57d38ddab5c3d 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js @@ -53,7 +53,7 @@ describe('Kuery operator suggestions', function () { const suggestions = getSuggestions({ fieldName }); expect(suggestions.length).to.be.greaterThan(0); suggestions.forEach(suggestion => { - expect(suggestion.description.length).to.be.greaterThan(0); + expect(suggestion).to.have.property('description'); }); }); }); diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/conjunction.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/conjunction.js index eab4ba014ff6a..8ea90ae89d25e 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/conjunction.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/conjunction.js @@ -3,37 +3,48 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; const type = 'conjunction'; -const bothArgumentsText = i18n.translate('xpack.kueryAutocomplete.andOperatorDescription.bothArgumentsText', { - defaultMessage: 'both arguments', - description: 'Part of xpack.kueryAutocomplete.andOperatorDescription. Full text: "Requires both arguments to be true"' -}); -const oneOrMoreArgumentsText = i18n.translate('xpack.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText', { - defaultMessage: 'one or more arguments', - description: 'Part of xpack.kueryAutocomplete.orOperatorDescription. Full text: "Requires one or more arguments to be true"' -}); +const bothArgumentsText = + (); + +const oneOrMoreArgumentsText = + (); const conjunctions = { - and: '

    ' + - i18n.translate('xpack.kueryAutocomplete.andOperatorDescription', { - defaultMessage: 'Requires {bothArguments} to be true', - values: { bothArguments: `${bothArgumentsText}` }, - description: 'Full text: "Requires both arguments to be true". See ' + - 'xpack.kueryAutocomplete.andOperatorDescription.bothArgumentsText for "both arguments" part.' - }) + - '

    ', - or: '

    ' + - i18n.translate('xpack.kueryAutocomplete.orOperatorDescription', { - defaultMessage: 'Requires {oneOrMoreArguments} to be true', - values: { oneOrMoreArguments: `${oneOrMoreArgumentsText}` }, - description: 'Full text: "Requires one or more arguments to be true". See ' + - 'xpack.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText for "one or more arguments" part.' - }) + - '

    ' + and: ( +

    + {bothArgumentsText} }} + description="Full text: ' Requires both arguments to be true'. See + 'xpack.kueryAutocomplete.andOperatorDescription.bothArgumentsText' for 'both arguments' part." + /> +

    + ), + or: ( +

    + {oneOrMoreArgumentsText} }} + description="Full text: 'Requires one or more arguments to be true'. See + 'xpack.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText' for 'one or more arguments' part." + /> +

    + ) }; function getDescription(conjunction) { diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/field.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/field.js index a9266d44bf7d2..60c4e5ffc4121 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/field.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/field.js @@ -3,23 +3,26 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -import { escape, flatten } from 'lodash'; +import React from 'react'; +import { flatten } from 'lodash'; import { escapeKuery } from './escape_kuery'; import { sortPrefixFirst } from 'ui/utils/sort_prefix_first'; import { isFilterable } from 'ui/index_patterns/static_utils'; -import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; const type = 'field'; function getDescription(fieldName) { - return '

    ' + - i18n.translate('xpack.kueryAutocomplete.filterResultsDescription', { - defaultMessage: 'Filter results that contain {fieldName}', - values: { fieldName: `${escape(fieldName)}` } - }) + - '

    '; + return ( +

    + {fieldName} }} + /> +

    + ); } export function getSuggestionsProvider({ indexPatterns }) { diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/operator.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/operator.js index 2988fe2cf5b7d..a60216bd9316a 100644 --- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/operator.js +++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/operator.js @@ -4,95 +4,119 @@ * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; - +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { flatten } from 'lodash'; const type = 'operator'; -const equalsText = i18n.translate('xpack.kueryAutocomplete.equalOperatorDescription.equalsText', { - defaultMessage: 'equals', - description: 'Part of xpack.kueryAutocomplete.equalOperatorDescription. Full text: "equals some value"' -}); -const lessThanOrEqualToText = i18n.translate('xpack.kueryAutocomplete.lessThanOrEqualOperatorDescription.lessThanOrEqualToText', { - defaultMessage: 'less than or equal to', - description: 'Part of xpack.kueryAutocomplete.lessThanOrEqualOperatorDescription. Full text: "is less than or equal to some value"' -}); -const greaterThanOrEqualToText = i18n.translate('xpack.kueryAutocomplete.greaterThanOrEqualOperatorDescription.greaterThanOrEqualToText', { - defaultMessage: 'greater than or equal to', - description: 'Part of xpack.kueryAutocomplete.greaterThanOrEqualOperatorDescription. Full text: "is greater than or equal to some value"' -}); -const lessThanText = i18n.translate('xpack.kueryAutocomplete.lessThanOperatorDescription.lessThanText', { - defaultMessage: 'less than', - description: 'Part of xpack.kueryAutocomplete.lessThanOperatorDescription. Full text: "is less than some value"' -}); -const greaterThanText = i18n.translate('xpack.kueryAutocomplete.greaterThanOperatorDescription.greaterThanText', { - defaultMessage: 'greater than', - description: 'Part of xpack.kueryAutocomplete.greaterThanOperatorDescription. Full text: "is greater than some value"' -}); -const existsText = i18n.translate('xpack.kueryAutocomplete.existOperatorDescription.existsText', { - defaultMessage: 'exists', - description: 'Part of xpack.kueryAutocomplete.existOperatorDescription. Full text: "exists in any form"' -}); +const equalsText = ( + ); +const lessThanOrEqualToText = ( + ); +const greaterThanOrEqualToText = ( + ); +const lessThanText = ( + ); +const greaterThanText = ( + ); +const existsText = ( + ); const operators = { ':': { - description: i18n.translate('xpack.kueryAutocomplete.equalOperatorDescription', { - defaultMessage: '{equals} some value', - values: { equals: `${equalsText}` }, - description: 'Full text: "equals some value". See ' + - 'xpack.kueryAutocomplete.equalOperatorDescription.equalsText for "equals" part.' - }), + description: ( + {equalsText} }} + description="Full text: 'equals some value'. See + 'xpack.kueryAutocomplete.equalOperatorDescription.equalsText' for 'equals' part." + />), fieldTypes: ['string', 'number', 'date', 'ip', 'geo_point', 'geo_shape', 'boolean'] }, '<=': { - description: i18n.translate('xpack.kueryAutocomplete.lessThanOrEqualOperatorDescription', { - defaultMessage: 'is {lessThanOrEqualTo} some value', - values: { lessThanOrEqualTo: `${lessThanOrEqualToText}` }, - description: 'Full text: "is less than or equal to some value". See ' + - 'xpack.kueryAutocomplete.lessThanOrEqualOperatorDescription.lessThanOrEqualToText for "less than or equal to" part.' - }), + description: ( + {lessThanOrEqualToText} }} + description="Full text: 'is less than or equal to some value'. See + 'xpack.kueryAutocomplete.lessThanOrEqualOperatorDescription.lessThanOrEqualToText' for 'less than or equal to' part." + />), fieldTypes: ['number', 'date', 'ip'] }, '>=': { - description: i18n.translate('xpack.kueryAutocomplete.greaterThanOrEqualOperatorDescription', { - defaultMessage: 'is {greaterThanOrEqualTo} some value', - values: { greaterThanOrEqualTo: `${greaterThanOrEqualToText}` }, - description: 'Full text: "is greater than or equal to some value". See ' + - 'xpack.kueryAutocomplete.greaterThanOrEqualOperatorDescription.greaterThanOrEqualToText for "greater than or equal to" part.' - }), + description: ( + {greaterThanOrEqualToText} }} + description="Full text: 'is greater than or equal to some value'. See + 'xpack.kueryAutocomplete.greaterThanOrEqualOperatorDescription.greaterThanOrEqualToText' for 'greater than or equal to' part." + />), fieldTypes: ['number', 'date', 'ip'] }, '<': { - description: i18n.translate('xpack.kueryAutocomplete.lessThanOperatorDescription', { - defaultMessage: 'is {lessThan} some value', - values: { lessThan: `${lessThanText}` }, - description: 'Full text: "is less than some value". See ' + - 'xpack.kueryAutocomplete.lessThanOperatorDescription.lessThanText for "less than" part.' - }), + description: ( + {lessThanText} }} + description="Full text: 'is less than some value'. See + 'xpack.kueryAutocomplete.lessThanOperatorDescription.lessThanText' for 'less than' part." + />), fieldTypes: ['number', 'date', 'ip'] }, '>': { - description: i18n.translate('xpack.kueryAutocomplete.greaterThanOperatorDescription', { - defaultMessage: 'is {greaterThan} some value', - values: { greaterThan: `${greaterThanText}` }, - description: 'Full text: "is greater than some value". See ' + - 'xpack.kueryAutocomplete.greaterThanOperatorDescription.greaterThanText for "greater than" part.' - }), + description: ( + {greaterThanText} }} + description="Full text: 'is greater than some value'. See + 'xpack.kueryAutocomplete.greaterThanOperatorDescription.greaterThanText' for 'greater than' part." + />), fieldTypes: ['number', 'date', 'ip'] }, ':*': { - description: i18n.translate('xpack.kueryAutocomplete.existOperatorDescription', { - defaultMessage: '{exists} in any form', - values: { exists: `${existsText}` }, - description: 'Full text: "exists in any form". See ' + - 'xpack.kueryAutocomplete.existOperatorDescription.existsText for "exists" part.' - }) + description: ( + {existsText} }} + description="Full text: 'exists in any form'. See + 'xpack.kueryAutocomplete.existOperatorDescription.existsText' for 'exists' part." + />) }, }; function getDescription(operator) { const { description } = operators[operator]; - return `

    ${description}

    `; + return

    {description}

    ; } export function getSuggestionsProvider({ indexPatterns }) { diff --git a/x-pack/plugins/ml/public/components/kql_filter_bar/suggestion/__snapshots__/suggestion.test.js.snap b/x-pack/plugins/ml/public/components/kql_filter_bar/suggestion/__snapshots__/suggestion.test.js.snap index f8f765ac97594..4eb236f50be05 100644 --- a/x-pack/plugins/ml/public/components/kql_filter_bar/suggestion/__snapshots__/suggestion.test.js.snap +++ b/x-pack/plugins/ml/public/components/kql_filter_bar/suggestion/__snapshots__/suggestion.test.js.snap @@ -17,12 +17,8 @@ exports[`Suggestion snapshot 1`] = ` fieldValue - Test description for fieldValue

    ", - } - } - /> + + <p>Test description for fieldValue</p> + `; diff --git a/x-pack/plugins/ml/public/components/kql_filter_bar/suggestion/suggestion.js b/x-pack/plugins/ml/public/components/kql_filter_bar/suggestion/suggestion.js index e0c9a25ccb75e..aae16aa6de845 100644 --- a/x-pack/plugins/ml/public/components/kql_filter_bar/suggestion/suggestion.js +++ b/x-pack/plugins/ml/public/components/kql_filter_bar/suggestion/suggestion.js @@ -106,9 +106,7 @@ export const Suggestion = (props) => { {props.suggestion.text} - + {props.suggestion.description} ); }; From 283fd2e4a62753fd5c4dff50eeca1eaf484c2692 Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Thu, 28 Mar 2019 15:02:17 -0500 Subject: [PATCH 96/96] Fix regex to select paths correctly. (#34106) --- src/dev/jest/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js index bbb2b067c2261..e8d78abf1210e 100644 --- a/src/dev/jest/config.js +++ b/src/dev/jest/config.js @@ -44,7 +44,7 @@ export default { '!packages/kbn-ui-framework/src/services/**/*/index.js', ], moduleNameMapper: { - '^plugins/(.*)/(.*)': '/src/legacy/core_plugins/$1/public/$2', + '^plugins/([^\/.]*)/(.*)': '/src/legacy/core_plugins/$1/public/$2', '^ui/(.*)': '/src/legacy/ui/public/$1', '^uiExports/(.*)': '/src/dev/jest/mocks/file_mock.js', '^test_utils/(.*)': '/src/test_utils/public/$1',