You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by fj...@apache.org on 2019/05/23 03:36:59 UTC

[incubator-druid] branch master updated: add tests to dialogs, compnents and views. Add index files to components and dialogs. add nested file structure (#7669)

This is an automated email from the ASF dual-hosted git repository.

fjy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 1b284ca  add tests to dialogs, compnents and views. Add index files to components and dialogs. add nested file structure (#7669)
1b284ca is described below

commit 1b284ca847aaeb1fdfd9ac1b71dab95f9455169f
Author: mcbrewster <37...@users.noreply.github.com>
AuthorDate: Wed May 22 20:36:51 2019 -0700

    add tests to dialogs, compnents and views. Add index files to components and dialogs. add nested file structure (#7669)
---
 pom.xml                                            |    1 +
 web-console/.gitignore                             |    1 +
 web-console/package-lock.json                      | 2351 +++++++++++++-------
 web-console/package.json                           |   20 +-
 web-console/src/bootstrap/react-table-defaults.tsx |    2 +-
 .../__snapshots__/action-cell.spec.tsx.snap        |   11 +
 .../components/{ => action-cell}/action-cell.scss  |    0
 .../action-cell.spec.tsx}                          |   27 +-
 .../components/{ => action-cell}/action-cell.tsx   |    0
 .../__snapshots__/array-input.spec.tsx.snap        |   10 +
 .../array-input.spec.tsx}                          |   35 +-
 .../components/{ => array-input}/array-input.tsx   |    9 +-
 .../__snapshots__/auto-form.spec.tsx.snap          |  489 ++++
 .../src/components/{ => auto-form}/auto-form.scss  |    0
 .../auto-form.spec.tsx}                            |   29 +-
 .../src/components/{ => auto-form}/auto-form.tsx   |   17 +-
 .../__snapshots__/center-message.spec.tsx.snap     |   15 +
 .../{ => center-message}/center-message.scss       |    0
 .../center-message.spec.tsx}                       |   26 +-
 .../{ => center-message}/center-message.tsx        |    0
 .../__snapshots__/clearable-input.spec.tsx.snap    |   43 +
 .../clearable-input.spec.tsx}                      |   34 +-
 .../{ => clearable-input}/clearable-input.tsx      |    0
 .../__snapshots__/external-link.spec.tsx.snap      |   12 +
 .../external-link.spec.tsx}                        |   26 +-
 .../{ => external-link}/external-link.tsx          |    0
 .../__snapshots__/header-bar.spec.tsx.snap         |  290 +++
 .../components/{ => header-bar}/header-bar.scss    |    0
 .../header-bar.spec.tsx}                           |   27 +-
 .../src/components/{ => header-bar}/header-bar.tsx |   10 +-
 .../src/components/{auto-form.scss => index.ts}    |   41 +-
 .../__snapshots__/json-collapse.spec.tsx.snap      |   29 +
 .../json-collapse.spec.tsx}                        |   28 +-
 .../{ => json-collapse}/json-collapse.tsx          |    0
 .../__snapshots__/json-collapse.spec.tsx.snap      |   93 +
 .../json-collapse.spec.tsx}                        |   28 +-
 .../src/components/{ => json-input}/json-input.tsx |    2 +-
 .../loader/__snapshots__/loader.spec.tsx.snap      |   42 +
 .../src/components/{ => loader}/loader.scss        |    0
 .../{external-link.tsx => loader/loader.spec.tsx}  |   28 +-
 web-console/src/components/{ => loader}/loader.tsx |    0
 .../__snapshots__/menu-checkbox.spec.tsx.snap      |   18 +
 .../{ => menu-checkbox}/menu-checkbox.scss         |    0
 .../menu-checkbox.spec.tsx}                        |   25 +-
 .../{ => menu-checkbox}/menu-checkbox.tsx          |    0
 .../__snapshots__/null-table-cell.spec.tsx.snap    |    3 +
 .../{ => null-table-cell}/null-table-cell.scss     |    0
 .../null-table-cell.spec.tsx}                      |   29 +-
 .../{ => null-table-cell}/null-table-cell.tsx      |    1 +
 .../__snapshots__/rule-editor.spec.tsx.snap        |  220 ++
 .../components/{ => rule-editor}/rule-editor.scss  |    0
 .../rule-editor.spec.tsx}                          |   32 +-
 .../components/{ => rule-editor}/rule-editor.tsx   |    0
 .../__snapshots__/show-json.spec.tsx.snap          |   54 +
 .../src/components/{ => show-json}/show-json.scss  |    0
 .../show-json.spec.tsx}                            |   27 +-
 .../src/components/{ => show-json}/show-json.tsx   |    6 +-
 .../show-log/__snapshots__/show-log.spec.tsx.snap  |   54 +
 .../src/components/{ => show-log}/show-log.scss    |    0
 .../show-log.spec.tsx}                             |   27 +-
 .../src/components/{ => show-log}/show-log.tsx     |    6 +-
 .../__snapshots__/sql-control.spec.tsx.snap        |  172 ++
 .../components/{ => sql-control}/sql-control.scss  |    0
 .../sql-control.spec.tsx}                          |   29 +-
 .../components/{ => sql-control}/sql-control.tsx   |    9 +-
 .../table-column-selection.spec.tsx.snap           |   41 +
 .../{ => table-column}/table-column-selection.scss |    0
 .../table-column-selection.spec.tsx}               |   29 +-
 .../{ => table-column}/table-column-selection.tsx  |    2 +-
 .../__snapshots__/view-control-bar.spec.tsx.snap   |   16 +
 .../{ => view-control-bar}/view-control-bar.scss   |    0
 .../view-control-bar.spec.tsx}                     |   26 +-
 .../{ => view-control-bar}/view-control-bar.tsx    |    0
 web-console/src/console-application.tsx            |   22 +-
 .../__snapshots__/about-dialog.spec.tsx.snap       |  145 ++
 .../about-dialog/about-dialog.spec.tsx}            |   27 +-
 .../dialogs/{ => about-dialog}/about-dialog.tsx    |    4 +-
 .../async-action-dialog.spec.tsx.snap              |   56 +
 .../async-action-dialog.spec.tsx}                  |   35 +-
 .../async-action-dialog.tsx                        |    2 +-
 .../__snapshots__/compaction-dialog.spec.tsx.snap  |  731 ++++++
 .../{ => compaction-dialog}/compaction-dialog.scss |    0
 .../compaction-dialog/compaction-dialog.spec.tsx}  |   35 +-
 .../{ => compaction-dialog}/compaction-dialog.tsx  |    2 +-
 .../coordinator-dynamic-config.spec.tsx.snap       |  123 +
 .../coordinator-dynamic-config.scss                |    0
 .../coordinator-dynamic-config.spec.tsx}           |   31 +-
 .../coordinator-dynamic-config.tsx                 |   11 +-
 .../__snapshots__/history-dialog.spec.tsx.snap     |  132 ++
 .../{ => history-dialog}/history-dialog.scss       |    0
 .../history-dialog/history-dialog.spec.tsx}        |   32 +-
 .../{ => history-dialog}/history-dialog.tsx        |    2 +-
 .../clearable-input.tsx => dialogs/index.ts}       |   40 +-
 .../__snapshots__/lookup-edit-dialog.spec.tsx.snap |  356 +++
 .../lookup-edit-dialog.scss                        |    0
 .../lookup-edit-dialog.spec.tsx}                   |   44 +-
 .../lookup-edit-dialog.tsx                         |    2 +-
 .../overload-dynamic-config.spec.tsx.snap          |  356 +++
 .../overload-dynamic-config.spec.tsx}              |   32 +-
 .../overlord-dynamic-config.scss                   |    0
 .../overlord-dynamic-config.tsx                    |   11 +-
 .../__snapshots__/query-plan-dialog.spec.tsx.snap  |   84 +
 .../{ => query-plan-dialog}/query-plan-dialog.scss |    0
 .../query-plan-dialog/query-plan-dialog.spec.tsx}  |   33 +-
 .../{ => query-plan-dialog}/query-plan-dialog.tsx  |    2 +-
 .../__snapshots__/retention-dialog.spec.tsx.snap   |  173 ++
 .../retention-dialog.array.spec.ts}                |    0
 .../{ => retention-dialog}/retention-dialog.scss   |    0
 .../retention-dialog/retention-dialog.spec.tsx}    |   36 +-
 .../{ => retention-dialog}/retention-dialog.tsx    |    7 +-
 .../__snapshots__/snitch-dialog.spec.tsx.snap      |   65 +
 .../dialogs/{ => snitch-dialog}/snitch-dialog.scss |    0
 .../snitch-dialog/snitch-dialog.spec.tsx}          |   29 +-
 .../dialogs/{ => snitch-dialog}/snitch-dialog.tsx  |    2 +-
 .../__snapshots__/spec-dialog.spec.tsx.snap        |  174 ++
 .../src/dialogs/{ => spec-dialog}/spec-dialog.scss |    0
 .../spec-dialog/spec-dialog.spec.tsx}              |   30 +-
 .../src/dialogs/{ => spec-dialog}/spec-dialog.tsx  |    2 -
 .../supervisor-table-action-dialog.spec.tsx.snap   |  299 +++
 .../supervisor-table-action-dialog.spec.tsx}       |   28 +-
 .../supervisor-table-action-dialog.tsx             |    7 +-
 .../table-action-dialog.spec.tsx.snap              |   86 +
 .../table-action-dialog.scss                       |    0
 .../table-action-dialog.spec.tsx}                  |   33 +-
 .../table-action-dialog.tsx                        |    0
 .../task-table-action-dialog.spec.tsx.snap         |  269 +++
 .../task-table-action-dialog.spec.tsx}             |   33 +-
 .../task-table-action-dialog.tsx                   |    9 +-
 .../src/{views/tasks-view.scss => setup-tests.ts}  |   12 +-
 web-console/src/utils/ingestion-spec.tsx           |    4 +-
 .../__snapshots__/datasource-view.spec.tsx.snap    |  296 +++
 .../{ => datasource-view}/datasource-view.scss     |    0
 .../datasource-view/datasource-view.spec.tsx}      |   28 +-
 .../{ => datasource-view}/datasource-view.tsx      |   18 +-
 .../__snapshots__/home-view.spec.tsx.snap          |  135 ++
 .../src/views/{ => home-view}/home-view.scss       |    2 +-
 .../home-view/home-view.spec.tsx}                  |   33 +-
 .../src/views/{ => home-view}/home-view.tsx        |    4 +-
 web-console/{jest.config.js => src/views/index.ts} |   23 +-
 .../__snapshots__/load-data-view.spec.tsx.snap     |  212 ++
 .../views/{ => load-data-view}/load-data-view.scss |    0
 .../load-data-view/load-data-view.spec.tsx}        |   33 +-
 .../views/{ => load-data-view}/load-data-view.tsx  |   31 +-
 .../__snapshots__/lookups-view.spec.tsx.snap       |  231 ++
 .../src/views/{ => lookups-view}/lookups-view.scss |    0
 .../lookups-view/lookups-view.spec.tsx}            |   28 +-
 .../src/views/{ => lookups-view}/lookups-view.tsx  |   10 +-
 .../__snapshots__/segments-view.spec.tsx.snap      |  452 ++++
 .../views/{ => segments-view}/segments-view.scss   |    0
 .../segments-view/segments-view.spec.tsx}          |   37 +-
 .../views/{ => segments-view}/segments-view.tsx    |    5 +-
 .../__snapshots__/servers-view.spec.tsx.snap       |  452 ++++
 .../src/views/{ => servers-view}/servers-view.scss |    2 +-
 .../servers-view/servers-view.spec.tsx}            |   37 +-
 .../src/views/{ => servers-view}/servers-view.tsx  |    5 +-
 .../sql-view/__snapshots__/sql-view.spec.tsx.snap  |  147 ++
 web-console/src/views/{ => sql-view}/sql-view.scss |    2 +-
 .../sql-view/sql-view.spec.tsx}                    |   34 +-
 web-console/src/views/{ => sql-view}/sql-view.tsx  |    7 +-
 .../__snapshots__/tasks-view.spec.tsx.snap         |  592 +++++
 .../src/views/{ => task-view}/tasks-view.scss      |    2 +-
 .../task-view/tasks-view.spec.tsx}                 |   39 +-
 .../src/views/{ => task-view}/tasks-view.tsx       |   15 +-
 163 files changed, 9553 insertions(+), 1609 deletions(-)

diff --git a/pom.xml b/pom.xml
index 8219edc..df24ca8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1563,6 +1563,7 @@
                                 <exclude>git.version</exclude>
                                 <exclude>node_modules/**</exclude>
                                 <exclude>coordinator-console/**</exclude>
+                                <exclude>src/**/*.snap</exclude>
                             </excludes>
                         </configuration>
                     </plugin>
diff --git a/web-console/.gitignore b/web-console/.gitignore
index a18416a..016043f 100644
--- a/web-console/.gitignore
+++ b/web-console/.gitignore
@@ -3,6 +3,7 @@ node_modules/
 resources/
 public/
 lib/*.css
+coverage/
 
 coordinator-console/
 pages/
diff --git a/web-console/package-lock.json b/web-console/package-lock.json
index e3ee018..90290f2 100644
--- a/web-console/package-lock.json
+++ b/web-console/package-lock.json
@@ -14,18 +14,18 @@
       }
     },
     "@babel/core": {
-      "version": "7.4.3",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.3.tgz",
-      "integrity": "sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.4.tgz",
+      "integrity": "sha512-lQgGX3FPRgbz2SKmhMtYgJvVzGZrmjaF4apZ2bLwofAKiSjxU0drPh4S/VasyYXwaTs+A1gvQ45BN8SQJzHsQQ==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "@babel/generator": "^7.4.0",
-        "@babel/helpers": "^7.4.3",
-        "@babel/parser": "^7.4.3",
-        "@babel/template": "^7.4.0",
-        "@babel/traverse": "^7.4.3",
-        "@babel/types": "^7.4.0",
+        "@babel/generator": "^7.4.4",
+        "@babel/helpers": "^7.4.4",
+        "@babel/parser": "^7.4.4",
+        "@babel/template": "^7.4.4",
+        "@babel/traverse": "^7.4.4",
+        "@babel/types": "^7.4.4",
         "convert-source-map": "^1.1.0",
         "debug": "^4.1.0",
         "json5": "^2.1.0",
@@ -62,12 +62,12 @@
       }
     },
     "@babel/generator": {
-      "version": "7.4.0",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz",
-      "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz",
+      "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.4.0",
+        "@babel/types": "^7.4.4",
         "jsesc": "^2.5.1",
         "lodash": "^4.17.11",
         "source-map": "^0.5.0",
@@ -109,23 +109,23 @@
       "dev": true
     },
     "@babel/helper-split-export-declaration": {
-      "version": "7.4.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz",
-      "integrity": "sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz",
+      "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.4.0"
+        "@babel/types": "^7.4.4"
       }
     },
     "@babel/helpers": {
-      "version": "7.4.3",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.3.tgz",
-      "integrity": "sha512-BMh7X0oZqb36CfyhvtbSmcWc3GXocfxv3yNsAEuM0l+fAqSO22rQrUpijr3oE/10jCTrB6/0b9kzmG4VetCj8Q==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz",
+      "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==",
       "dev": true,
       "requires": {
-        "@babel/template": "^7.4.0",
-        "@babel/traverse": "^7.4.3",
-        "@babel/types": "^7.4.0"
+        "@babel/template": "^7.4.4",
+        "@babel/traverse": "^7.4.4",
+        "@babel/types": "^7.4.4"
       }
     },
     "@babel/highlight": {
@@ -140,9 +140,9 @@
       }
     },
     "@babel/parser": {
-      "version": "7.4.3",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz",
-      "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.4.tgz",
+      "integrity": "sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w==",
       "dev": true
     },
     "@babel/plugin-syntax-object-rest-spread": {
@@ -155,36 +155,36 @@
       }
     },
     "@babel/runtime": {
-      "version": "7.4.3",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.3.tgz",
-      "integrity": "sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.4.tgz",
+      "integrity": "sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==",
       "requires": {
         "regenerator-runtime": "^0.13.2"
       }
     },
     "@babel/template": {
-      "version": "7.4.0",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.0.tgz",
-      "integrity": "sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz",
+      "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "@babel/parser": "^7.4.0",
-        "@babel/types": "^7.4.0"
+        "@babel/parser": "^7.4.4",
+        "@babel/types": "^7.4.4"
       }
     },
     "@babel/traverse": {
-      "version": "7.4.3",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.3.tgz",
-      "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.4.tgz",
+      "integrity": "sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "@babel/generator": "^7.4.0",
+        "@babel/generator": "^7.4.4",
         "@babel/helper-function-name": "^7.1.0",
-        "@babel/helper-split-export-declaration": "^7.4.0",
-        "@babel/parser": "^7.4.3",
-        "@babel/types": "^7.4.0",
+        "@babel/helper-split-export-declaration": "^7.4.4",
+        "@babel/parser": "^7.4.4",
+        "@babel/types": "^7.4.4",
         "debug": "^4.1.0",
         "globals": "^11.1.0",
         "lodash": "^4.17.11"
@@ -202,9 +202,9 @@
       }
     },
     "@babel/types": {
-      "version": "7.4.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz",
-      "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==",
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz",
+      "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==",
       "dev": true,
       "requires": {
         "esutils": "^2.0.2",
@@ -266,32 +266,32 @@
       }
     },
     "@jest/core": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.7.1.tgz",
-      "integrity": "sha512-ivlZ8HX/FOASfHcb5DJpSPFps8ydfUYzLZfgFFqjkLijYysnIEOieg72YRhO4ZUB32xu40hsSMmaw+IGYeKONA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.8.0.tgz",
+      "integrity": "sha512-R9rhAJwCBQzaRnrRgAdVfnglUuATXdwTRsYqs6NMdVcAl5euG8LtWDe+fVkN27YfKVBW61IojVsXKaOmSnqd/A==",
       "dev": true,
       "requires": {
         "@jest/console": "^24.7.1",
-        "@jest/reporters": "^24.7.1",
-        "@jest/test-result": "^24.7.1",
-        "@jest/transform": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/reporters": "^24.8.0",
+        "@jest/test-result": "^24.8.0",
+        "@jest/transform": "^24.8.0",
+        "@jest/types": "^24.8.0",
         "ansi-escapes": "^3.0.0",
         "chalk": "^2.0.1",
         "exit": "^0.1.2",
         "graceful-fs": "^4.1.15",
-        "jest-changed-files": "^24.7.0",
-        "jest-config": "^24.7.1",
-        "jest-haste-map": "^24.7.1",
-        "jest-message-util": "^24.7.1",
+        "jest-changed-files": "^24.8.0",
+        "jest-config": "^24.8.0",
+        "jest-haste-map": "^24.8.0",
+        "jest-message-util": "^24.8.0",
         "jest-regex-util": "^24.3.0",
-        "jest-resolve-dependencies": "^24.7.1",
-        "jest-runner": "^24.7.1",
-        "jest-runtime": "^24.7.1",
-        "jest-snapshot": "^24.7.1",
-        "jest-util": "^24.7.1",
-        "jest-validate": "^24.7.0",
-        "jest-watcher": "^24.7.1",
+        "jest-resolve-dependencies": "^24.8.0",
+        "jest-runner": "^24.8.0",
+        "jest-runtime": "^24.8.0",
+        "jest-snapshot": "^24.8.0",
+        "jest-util": "^24.8.0",
+        "jest-validate": "^24.8.0",
+        "jest-watcher": "^24.8.0",
         "micromatch": "^3.1.10",
         "p-each-series": "^1.0.0",
         "pirates": "^4.0.1",
@@ -301,49 +301,50 @@
       }
     },
     "@jest/environment": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.7.1.tgz",
-      "integrity": "sha512-wmcTTYc4/KqA+U5h1zQd5FXXynfa7VGP2NfF+c6QeGJ7c+2nStgh65RQWNX62SC716dTtqheTRrZl0j+54oGHw==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.8.0.tgz",
+      "integrity": "sha512-vlGt2HLg7qM+vtBrSkjDxk9K0YtRBi7HfRFaDxoRtyi+DyVChzhF20duvpdAnKVBV6W5tym8jm0U9EfXbDk1tw==",
       "dev": true,
       "requires": {
-        "@jest/fake-timers": "^24.7.1",
-        "@jest/transform": "^24.7.1",
-        "@jest/types": "^24.7.0",
-        "jest-mock": "^24.7.0"
+        "@jest/fake-timers": "^24.8.0",
+        "@jest/transform": "^24.8.0",
+        "@jest/types": "^24.8.0",
+        "jest-mock": "^24.8.0"
       }
     },
     "@jest/fake-timers": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.7.1.tgz",
-      "integrity": "sha512-4vSQJDKfR2jScOe12L9282uiwuwQv9Lk7mgrCSZHA9evB9efB/qx8i0KJxsAKtp8fgJYBJdYY7ZU6u3F4/pyjA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.8.0.tgz",
+      "integrity": "sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0",
-        "jest-message-util": "^24.7.1",
-        "jest-mock": "^24.7.0"
+        "@jest/types": "^24.8.0",
+        "jest-message-util": "^24.8.0",
+        "jest-mock": "^24.8.0"
       }
     },
     "@jest/reporters": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.7.1.tgz",
-      "integrity": "sha512-bO+WYNwHLNhrjB9EbPL4kX/mCCG4ZhhfWmO3m4FSpbgr7N83MFejayz30kKjgqr7smLyeaRFCBQMbXpUgnhAJw==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.8.0.tgz",
+      "integrity": "sha512-eZ9TyUYpyIIXfYCrw0UHUWUvE35vx5I92HGMgS93Pv7du+GHIzl+/vh8Qj9MCWFK/4TqyttVBPakWMOfZRIfxw==",
       "dev": true,
       "requires": {
-        "@jest/environment": "^24.7.1",
-        "@jest/test-result": "^24.7.1",
-        "@jest/transform": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/environment": "^24.8.0",
+        "@jest/test-result": "^24.8.0",
+        "@jest/transform": "^24.8.0",
+        "@jest/types": "^24.8.0",
         "chalk": "^2.0.1",
         "exit": "^0.1.2",
         "glob": "^7.1.2",
-        "istanbul-api": "^2.1.1",
         "istanbul-lib-coverage": "^2.0.2",
         "istanbul-lib-instrument": "^3.0.1",
+        "istanbul-lib-report": "^2.0.4",
         "istanbul-lib-source-maps": "^3.0.1",
-        "jest-haste-map": "^24.7.1",
-        "jest-resolve": "^24.7.1",
-        "jest-runtime": "^24.7.1",
-        "jest-util": "^24.7.1",
+        "istanbul-reports": "^2.1.1",
+        "jest-haste-map": "^24.8.0",
+        "jest-resolve": "^24.8.0",
+        "jest-runtime": "^24.8.0",
+        "jest-util": "^24.8.0",
         "jest-worker": "^24.6.0",
         "node-notifier": "^5.2.1",
         "slash": "^2.0.0",
@@ -363,44 +364,44 @@
       }
     },
     "@jest/test-result": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.7.1.tgz",
-      "integrity": "sha512-3U7wITxstdEc2HMfBX7Yx3JZgiNBubwDqQMh+BXmZXHa3G13YWF3p6cK+5g0hGkN3iufg/vGPl3hLxQXD74Npg==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.8.0.tgz",
+      "integrity": "sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng==",
       "dev": true,
       "requires": {
         "@jest/console": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "@types/istanbul-lib-coverage": "^2.0.0"
       }
     },
     "@jest/test-sequencer": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.7.1.tgz",
-      "integrity": "sha512-84HQkCpVZI/G1zq53gHJvSmhUer4aMYp9tTaffW28Ih5OxfCg8hGr3nTSbL1OhVDRrFZwvF+/R9gY6JRkDUpUA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.8.0.tgz",
+      "integrity": "sha512-OzL/2yHyPdCHXEzhoBuq37CE99nkme15eHkAzXRVqthreWZamEMA0WoetwstsQBCXABhczpK03JNbc4L01vvLg==",
       "dev": true,
       "requires": {
-        "@jest/test-result": "^24.7.1",
-        "jest-haste-map": "^24.7.1",
-        "jest-runner": "^24.7.1",
-        "jest-runtime": "^24.7.1"
+        "@jest/test-result": "^24.8.0",
+        "jest-haste-map": "^24.8.0",
+        "jest-runner": "^24.8.0",
+        "jest-runtime": "^24.8.0"
       }
     },
     "@jest/transform": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.7.1.tgz",
-      "integrity": "sha512-EsOUqP9ULuJ66IkZQhI5LufCHlTbi7hrcllRMUEV/tOgqBVQi93+9qEvkX0n8mYpVXQ8VjwmICeRgg58mrtIEw==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.8.0.tgz",
+      "integrity": "sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA==",
       "dev": true,
       "requires": {
         "@babel/core": "^7.1.0",
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "babel-plugin-istanbul": "^5.1.0",
         "chalk": "^2.0.1",
         "convert-source-map": "^1.4.0",
         "fast-json-stable-stringify": "^2.0.0",
         "graceful-fs": "^4.1.15",
-        "jest-haste-map": "^24.7.1",
+        "jest-haste-map": "^24.8.0",
         "jest-regex-util": "^24.3.0",
-        "jest-util": "^24.7.1",
+        "jest-util": "^24.8.0",
         "micromatch": "^3.1.10",
         "realpath-native": "^1.1.0",
         "slash": "^2.0.0",
@@ -409,12 +410,13 @@
       }
     },
     "@jest/types": {
-      "version": "24.7.0",
-      "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.7.0.tgz",
-      "integrity": "sha512-ipJUa2rFWiKoBqMKP63Myb6h9+iT3FHRTF2M8OR6irxWzItisa8i4dcSg14IbvmXUnBlHBlUQPYUHWyX3UPpYA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.8.0.tgz",
+      "integrity": "sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg==",
       "dev": true,
       "requires": {
         "@types/istanbul-lib-coverage": "^2.0.0",
+        "@types/istanbul-reports": "^1.1.1",
         "@types/yargs": "^12.0.9"
       }
     },
@@ -434,10 +436,16 @@
       "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
       "dev": true
     },
+    "@sheerun/mutationobserver-shim": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz",
+      "integrity": "sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==",
+      "dev": true
+    },
     "@types/babel__core": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.1.tgz",
-      "integrity": "sha512-+hjBtgcFPYyCTo0A15+nxrCVJL7aC6Acg87TXd5OW3QhHswdrOLoles+ldL2Uk8q++7yIfl4tURtztccdeeyOw==",
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.2.tgz",
+      "integrity": "sha512-cfCCrFmiGY/yq0NuKNxIQvZFy9kY/1immpSpTngOnyIbD4+eJOG5mxphhHDv3CHL9GltO4GcKr54kGBg3RNdbg==",
       "dev": true,
       "requires": {
         "@babel/parser": "^7.1.0",
@@ -475,6 +483,15 @@
         "@babel/types": "^7.3.0"
       }
     },
+    "@types/cheerio": {
+      "version": "0.22.11",
+      "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.11.tgz",
+      "integrity": "sha512-x0X3kPbholdJZng9wDMhb2swvUi3UYRNAuWAmIPIWlfgAJZp//cql/qblE7181Mg7SjWVwq6ldCPCLn5AY/e7w==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*"
+      }
+    },
     "@types/classnames": {
       "version": "2.2.7",
       "resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.7.tgz",
@@ -492,6 +509,25 @@
       "resolved": "https://registry.npmjs.org/@types/dom4/-/dom4-2.0.1.tgz",
       "integrity": "sha512-kSkVAvWmMZiCYtvqjqQEwOmvKwcH+V4uiv3qPQ8pAh1Xl39xggGEo8gHUqV4waYGHezdFw0rKBR8Jt0CrQSDZA=="
     },
+    "@types/enzyme": {
+      "version": "3.9.2",
+      "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.9.2.tgz",
+      "integrity": "sha512-f8lXku9JIa6vReljhHmHqMvaRcabdJzuOOVoLGjQvoL4ikQu0aQaHMI4uR/BCStYcpSbktTov5GpL2iruHaykA==",
+      "dev": true,
+      "requires": {
+        "@types/cheerio": "*",
+        "@types/react": "*"
+      }
+    },
+    "@types/enzyme-adapter-react-16": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.5.tgz",
+      "integrity": "sha512-K7HLFTkBDN5RyRmU90JuYt8OWEY2iKUn43SDWEoBOXd/PowUWjLZ3Q6qMBiQuZeFYK/TOstaZxsnI0fXoAfLpg==",
+      "dev": true,
+      "requires": {
+        "@types/enzyme": "*"
+      }
+    },
     "@types/events": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
@@ -528,15 +564,34 @@
       "dev": true
     },
     "@types/istanbul-lib-coverage": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz",
-      "integrity": "sha512-eAtOAFZefEnfJiRFQBGw1eYqa5GTLCZ1y86N0XSI/D6EB+E8z6VPV/UL7Gi5UEclFqoQk+6NRqEDsfmDLXn8sg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz",
+      "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==",
       "dev": true
     },
+    "@types/istanbul-lib-report": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz",
+      "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==",
+      "dev": true,
+      "requires": {
+        "@types/istanbul-lib-coverage": "*"
+      }
+    },
+    "@types/istanbul-reports": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz",
+      "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==",
+      "dev": true,
+      "requires": {
+        "@types/istanbul-lib-coverage": "*",
+        "@types/istanbul-lib-report": "*"
+      }
+    },
     "@types/jest": {
-      "version": "24.0.11",
-      "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.11.tgz",
-      "integrity": "sha512-2kLuPC5FDnWIDvaJBzsGTBQaBbnDweznicvK7UGYzlIJP4RJR2a4A/ByLUXEyEgag6jz8eHdlWExGDtH3EYUXQ==",
+      "version": "24.0.13",
+      "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.13.tgz",
+      "integrity": "sha512-3m6RPnO35r7Dg+uMLj1+xfZaOgIHHHut61djNjzwExXN4/Pm9has9C6I1KMYSfz7mahDhWUOVg4HW/nZdv5Pww==",
       "dev": true,
       "requires": {
         "@types/jest-diff": "*"
@@ -549,9 +604,9 @@
       "dev": true
     },
     "@types/lodash": {
-      "version": "4.14.123",
-      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz",
-      "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==",
+      "version": "4.14.129",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.129.tgz",
+      "integrity": "sha512-oYaV0eSlnOacOr7i4X1FFdH8ttSlb57gu3I9MuStIv2CYkISEY84dNHYsC3bF6sNH7qYcu1BtVrCtQ8Q4KPTfQ==",
       "dev": true
     },
     "@types/lodash.debounce": {
@@ -570,9 +625,9 @@
       "dev": true
     },
     "@types/node": {
-      "version": "11.13.7",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.7.tgz",
-      "integrity": "sha512-suFHr6hcA9mp8vFrZTgrmqW2ZU3mbWsryQtQlY/QvwTISCw7nw/j+bCQPPohqmskhmqa5wLNuMHTTsc+xf1MQg==",
+      "version": "11.13.10",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.10.tgz",
+      "integrity": "sha512-leUNzbFTMX94TWaIKz8N15Chu55F9QSH+INKayQr5xpkasBQBRF3qQXfo3/dOnMU/dEIit+Y/SU8HyOjq++GwA==",
       "dev": true
     },
     "@types/numeral": {
@@ -588,9 +643,9 @@
       "dev": true
     },
     "@types/react": {
-      "version": "16.8.14",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.14.tgz",
-      "integrity": "sha512-26tFVJ1omGmzIdFTFmnC5zhz1GTaqCjxgUxV4KzWvsybF42P7/j4RBn6UeO3KbHPXqKWZszMXMoI65xIWm954A==",
+      "version": "16.8.17",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.17.tgz",
+      "integrity": "sha512-pln3mgc6VfkNg92WXODul/ONo140huK9OMsx62GlBlZ2lvjNK86PQJhYMPLO1i66aF5O9OPyZefogvNltBIszA==",
       "dev": true,
       "requires": {
         "@types/prop-types": "*",
@@ -616,9 +671,9 @@
       }
     },
     "@types/react-router": {
-      "version": "4.4.5",
-      "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-4.4.5.tgz",
-      "integrity": "sha512-12+VOu1+xiC8RPc9yrgHCyLI79VswjtuqeS2gPrMcywH6tkc8rGIUhs4LaL3AJPqo5d+RPnfRpNKiJ7MK2Qhcg==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.0.0.tgz",
+      "integrity": "sha512-0JjtJMxkQSyWUHTHaD3GhKf6rcZSUFmcQob8OlPTsbnxnIg2Nh3btkss4uke5CKVRtbCMipGU7My5jtfZQC+jw==",
       "dev": true,
       "requires": {
         "@types/history": "*",
@@ -626,9 +681,9 @@
       }
     },
     "@types/react-router-dom": {
-      "version": "4.3.2",
-      "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-4.3.2.tgz",
-      "integrity": "sha512-biesHodFxPgDxku2m08XwPeAfUYBcxAnrQG7pwFikuA3L2e3u2OKAb+Sb16bJuU3L5CTHd+Ivap+ke4mmGsHqQ==",
+      "version": "4.3.3",
+      "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-4.3.3.tgz",
+      "integrity": "sha512-xj0DmFjgvAqRfh/kJPO7apD5G30yPQe+8slu/dugioQOkdKpyzc4Fgk4hoTelm6CSHz7pI2PPsW5+Y6GRBF2zw==",
       "dev": true,
       "requires": {
         "@types/history": "*",
@@ -885,13 +940,13 @@
       "dev": true
     },
     "accepts": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
-      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
       "dev": true,
       "requires": {
-        "mime-types": "~2.1.18",
-        "negotiator": "0.6.1"
+        "mime-types": "~2.1.24",
+        "negotiator": "0.6.2"
       }
     },
     "acorn": {
@@ -930,6 +985,24 @@
       "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==",
       "dev": true
     },
+    "airbnb-prop-types": {
+      "version": "2.13.2",
+      "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.13.2.tgz",
+      "integrity": "sha512-2FN6DlHr6JCSxPPi25EnqGaXC4OC3/B3k1lCd6MMYrZ51/Gf/1qDfaR+JElzWa+Tl7cY2aYOlsYJGFeQyVHIeQ==",
+      "dev": true,
+      "requires": {
+        "array.prototype.find": "^2.0.4",
+        "function.prototype.name": "^1.1.0",
+        "has": "^1.0.3",
+        "is-regex": "^1.0.4",
+        "object-is": "^1.0.1",
+        "object.assign": "^4.1.0",
+        "object.entries": "^1.1.0",
+        "prop-types": "^15.7.2",
+        "prop-types-exact": "^1.2.0",
+        "react-is": "^16.8.6"
+      }
+    },
     "ajv": {
       "version": "6.10.0",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
@@ -1014,15 +1087,6 @@
         }
       }
     },
-    "append-transform": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
-      "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
-      "dev": true,
-      "requires": {
-        "default-require-extensions": "^2.0.0"
-      }
-    },
     "aproba": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
@@ -1037,6 +1101,38 @@
       "requires": {
         "delegates": "^1.0.0",
         "readable-stream": "^2.0.6"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "arg": {
@@ -1078,6 +1174,12 @@
       "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
       "dev": true
     },
+    "array-filter": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
+      "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=",
+      "dev": true
+    },
     "array-find-index": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
@@ -1120,6 +1222,27 @@
       "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
       "dev": true
     },
+    "array.prototype.find": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz",
+      "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "es-abstract": "^1.7.0"
+      }
+    },
+    "array.prototype.flat": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz",
+      "integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "es-abstract": "^1.10.0",
+        "function-bind": "^1.1.1"
+      }
+    },
     "arrify": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
@@ -1152,11 +1275,12 @@
       }
     },
     "assert": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
-      "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+      "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
       "dev": true,
       "requires": {
+        "object-assign": "^4.1.1",
         "util": "0.10.3"
       },
       "dependencies": {
@@ -1196,13 +1320,10 @@
       "dev": true
     },
     "async": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
-      "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
-      "dev": true,
-      "requires": {
-        "lodash": "^4.17.11"
-      }
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+      "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+      "dev": true
     },
     "async-each": {
       "version": "1.0.3",
@@ -1281,13 +1402,13 @@
       }
     },
     "babel-jest": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.7.1.tgz",
-      "integrity": "sha512-GPnLqfk8Mtt0i4OemjWkChi73A3ALs4w2/QbG64uAj8b5mmwzxc7jbJVRZt8NJkxi6FopVHog9S3xX6UJKb2qg==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.8.0.tgz",
+      "integrity": "sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw==",
       "dev": true,
       "requires": {
-        "@jest/transform": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/transform": "^24.8.0",
+        "@jest/types": "^24.8.0",
         "@types/babel__core": "^7.1.0",
         "babel-plugin-istanbul": "^5.1.0",
         "babel-preset-jest": "^24.6.0",
@@ -1296,14 +1417,14 @@
       }
     },
     "babel-plugin-istanbul": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.2.tgz",
-      "integrity": "sha512-U3ZVajC+Z69Gim7ZzmD4Wcsq76i/1hqDamBfowc1tWzWjybRy70iWfngP2ME+1CrgcgZ/+muIbPY/Yi0dxdIkQ==",
+      "version": "5.1.4",
+      "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz",
+      "integrity": "sha512-dySz4VJMH+dpndj0wjJ8JPs/7i1TdSPb1nRrn56/92pKOF9VKC1FMFJmMXjzlGGusnCAqujP6PBCiKq0sVA+YQ==",
       "dev": true,
       "requires": {
         "find-up": "^3.0.0",
-        "istanbul-lib-instrument": "^3.2.0",
-        "test-exclude": "^5.2.2"
+        "istanbul-lib-instrument": "^3.3.0",
+        "test-exclude": "^5.2.3"
       }
     },
     "babel-plugin-jest-hoist": {
@@ -1326,9 +1447,9 @@
       }
     },
     "bail": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz",
-      "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.4.tgz",
+      "integrity": "sha512-S8vuDB4w6YpRhICUDET3guPlQpaJl7od94tpZ0Fvnyp+MKW/HyDTcRDck+29C9g+d/qQHnddRH3+94kZdrW0Ww==",
       "dev": true
     },
     "balanced-match": {
@@ -1524,6 +1645,12 @@
         }
       }
     },
+    "boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+      "dev": true
+    },
     "brace": {
       "version": "0.11.1",
       "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz",
@@ -1669,14 +1796,14 @@
       }
     },
     "browserslist": {
-      "version": "4.5.5",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.5.tgz",
-      "integrity": "sha512-0QFO1r/2c792Ohkit5XI8Cm8pDtZxgNl2H6HU4mHrpYz7314pEYcsAVVatM0l/YmxPnEzh9VygXouj4gkFUTKA==",
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.0.tgz",
+      "integrity": "sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg==",
       "dev": true,
       "requires": {
-        "caniuse-lite": "^1.0.30000960",
-        "electron-to-chromium": "^1.3.124",
-        "node-releases": "^1.1.14"
+        "caniuse-lite": "^1.0.30000967",
+        "electron-to-chromium": "^1.3.133",
+        "node-releases": "^1.1.19"
       }
     },
     "bs-logger": {
@@ -1871,9 +1998,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30000962",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000962.tgz",
-      "integrity": "sha512-WXYsW38HK+6eaj5IZR16Rn91TGhU3OhbwjKZvJ4HN/XBIABLKfbij9Mnd3pM0VEwZSlltWjoWg3I8FQ0DGgNOA==",
+      "version": "1.0.30000969",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000969.tgz",
+      "integrity": "sha512-Kus0yxkoAJgVc0bax7S4gLSlFifCa7MnSZL9p9VuS/HIKEL4seaqh28KIQAAO50cD/rJ5CiJkJFapkdDAlhFxQ==",
       "dev": true
     },
     "capture-exit": {
@@ -1892,9 +2019,9 @@
       "dev": true
     },
     "ccount": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz",
-      "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.4.tgz",
+      "integrity": "sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w==",
       "dev": true
     },
     "chalk": {
@@ -1920,27 +2047,27 @@
       }
     },
     "character-entities": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz",
-      "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==",
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.3.tgz",
+      "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==",
       "dev": true
     },
     "character-entities-html4": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz",
-      "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.3.tgz",
+      "integrity": "sha512-SwnyZ7jQBCRHELk9zf2CN5AnGEc2nA+uKMZLHvcqhpPprjkYhiLn0DywMHgN5ttFZuITMATbh68M6VIVKwJbcg==",
       "dev": true
     },
     "character-entities-legacy": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz",
-      "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.3.tgz",
+      "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==",
       "dev": true
     },
     "character-reference-invalid": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz",
-      "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz",
+      "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==",
       "dev": true
     },
     "check-types": {
@@ -1949,10 +2076,24 @@
       "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==",
       "dev": true
     },
+    "cheerio": {
+      "version": "1.0.0-rc.3",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
+      "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
+      "dev": true,
+      "requires": {
+        "css-select": "~1.2.0",
+        "dom-serializer": "~0.1.1",
+        "entities": "~1.1.1",
+        "htmlparser2": "^3.9.1",
+        "lodash": "^4.15.0",
+        "parse5": "^3.0.1"
+      }
+    },
     "chokidar": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz",
-      "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==",
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz",
+      "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==",
       "dev": true,
       "requires": {
         "anymatch": "^2.0.0",
@@ -2091,9 +2232,9 @@
       "dev": true
     },
     "collapse-white-space": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz",
-      "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==",
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.5.tgz",
+      "integrity": "sha512-703bOOmytCYAX9cXYqoikYIx6twmFCXsnzRQheBcTG3nzKYBR4P/+wkYeH+Mvj7qUz8zZDtdyzbxfnEi/kYzRQ==",
       "dev": true
     },
     "collection-visit": {
@@ -2122,9 +2263,9 @@
       "dev": true
     },
     "combined-stream": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
-      "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
       "dev": true,
       "requires": {
         "delayed-stream": "~1.0.0"
@@ -2142,12 +2283,6 @@
       "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
       "dev": true
     },
-    "compare-versions": {
-      "version": "3.4.0",
-      "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.4.0.tgz",
-      "integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==",
-      "dev": true
-    },
     "component-emitter": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
@@ -2155,12 +2290,12 @@
       "dev": true
     },
     "compressible": {
-      "version": "2.0.16",
-      "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.16.tgz",
-      "integrity": "sha512-JQfEOdnI7dASwCuSPWIeVYwc/zMsu/+tRhoUvEfXz2gxOA2DNjmG5vhtFdBlhWPPGo+RdT9S3tgc/uH5qgDiiA==",
+      "version": "2.0.17",
+      "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz",
+      "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==",
       "dev": true,
       "requires": {
-        "mime-db": ">= 1.38.0 < 2"
+        "mime-db": ">= 1.40.0 < 2"
       }
     },
     "compression": {
@@ -2211,6 +2346,38 @@
         "inherits": "^2.0.3",
         "readable-stream": "^2.2.2",
         "typedarray": "^0.0.6"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "connect-history-api-fallback": {
@@ -2474,6 +2641,24 @@
         "postcss": "^7.0.5"
       }
     },
+    "css-select": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+      "dev": true,
+      "requires": {
+        "boolbase": "~1.0.0",
+        "css-what": "2.1",
+        "domutils": "1.5.1",
+        "nth-check": "~1.0.1"
+      }
+    },
+    "css-what": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+      "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
+      "dev": true
+    },
     "cssdb": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz",
@@ -2624,15 +2809,6 @@
         "ip-regex": "^2.1.0"
       }
     },
-    "default-require-extensions": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
-      "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
-      "dev": true,
-      "requires": {
-        "strip-bom": "^3.0.0"
-      }
-    },
     "define-properties": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
@@ -2683,11 +2859,12 @@
       }
     },
     "del": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/del/-/del-4.1.0.tgz",
-      "integrity": "sha512-C4kvKNlYrwXhKxz97BuohF8YoGgQ23Xm9lvoHmgT7JaPGprSEjk3+XFled74Yt/x0ZABUHg2D67covzAPUKx5Q==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz",
+      "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==",
       "dev": true,
       "requires": {
+        "@types/glob": "^7.1.1",
         "globby": "^6.1.0",
         "is-path-cwd": "^2.0.0",
         "is-path-in-cwd": "^2.0.0",
@@ -2830,6 +3007,12 @@
         "path-type": "^3.0.0"
       }
     },
+    "discontinuous-range": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
+      "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=",
+      "dev": true
+    },
     "dns-equal": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
@@ -2873,6 +3056,18 @@
         "entities": "^1.1.1"
       }
     },
+    "dom-testing-library": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/dom-testing-library/-/dom-testing-library-4.1.0.tgz",
+      "integrity": "sha512-654GHd0oPC31S+ll1bJH9NUOBRzcHcrf23/XzJh41o6g67uGUpF9tn23qmbcwjNauoRqKQfAdHCDwr/Ez/Ot7A==",
+      "dev": true,
+      "requires": {
+        "@babel/runtime": "^7.4.3",
+        "@sheerun/mutationobserver-shim": "^0.3.2",
+        "pretty-format": "^24.7.0",
+        "wait-for-expect": "^1.1.1"
+      }
+    },
     "dom4": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/dom4/-/dom4-2.1.4.tgz",
@@ -2909,9 +3104,9 @@
       }
     },
     "domutils": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
-      "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+      "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
       "dev": true,
       "requires": {
         "dom-serializer": "0",
@@ -2948,6 +3143,38 @@
         "inherits": "^2.0.1",
         "readable-stream": "^2.0.0",
         "stream-shift": "^1.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "ecc-jsbn": {
@@ -2973,9 +3200,9 @@
       "dev": true
     },
     "electron-to-chromium": {
-      "version": "1.3.125",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.125.tgz",
-      "integrity": "sha512-XxowpqQxJ4nDwUXHtVtmEhRqBpm2OnjBomZmZtHD0d2Eo0244+Ojezhk3sD/MBSSe2nxCdGQFRXHIsf/LUTL9A==",
+      "version": "1.3.134",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.134.tgz",
+      "integrity": "sha512-C3uK2SrtWg/gSWaluLHWSHjyebVZCe4ZC0NVgTAoTq8tCR9FareRK5T7R7AS/nPZShtlEcjVMX1kQ8wi4nU68w==",
       "dev": true
     },
     "elliptic": {
@@ -3045,30 +3272,97 @@
       "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
       "dev": true
     },
-    "errno": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
-      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+    "enzyme": {
+      "version": "3.9.0",
+      "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.9.0.tgz",
+      "integrity": "sha512-JqxI2BRFHbmiP7/UFqvsjxTirWoM1HfeaJrmVSZ9a1EADKkZgdPcAuISPMpoUiHlac9J4dYt81MC5BBIrbJGMg==",
       "dev": true,
       "requires": {
-        "prr": "~1.0.1"
+        "array.prototype.flat": "^1.2.1",
+        "cheerio": "^1.0.0-rc.2",
+        "function.prototype.name": "^1.1.0",
+        "has": "^1.0.3",
+        "html-element-map": "^1.0.0",
+        "is-boolean-object": "^1.0.0",
+        "is-callable": "^1.1.4",
+        "is-number-object": "^1.0.3",
+        "is-regex": "^1.0.4",
+        "is-string": "^1.0.4",
+        "is-subset": "^0.1.1",
+        "lodash.escape": "^4.0.1",
+        "lodash.isequal": "^4.5.0",
+        "object-inspect": "^1.6.0",
+        "object-is": "^1.0.1",
+        "object.assign": "^4.1.0",
+        "object.entries": "^1.0.4",
+        "object.values": "^1.0.4",
+        "raf": "^3.4.0",
+        "rst-selector-parser": "^2.2.3",
+        "string.prototype.trim": "^1.1.2"
       }
     },
-    "error-ex": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
-      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+    "enzyme-adapter-react-16": {
+      "version": "1.13.0",
+      "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.13.0.tgz",
+      "integrity": "sha512-ZUVo9XATKrKavfe9v61EiYDu6V1NJCKtJyp1X2ILPgtuGQ58bItUR9uWwH6gzKJNww3sUiXM826jIiwPgO9iVQ==",
       "dev": true,
       "requires": {
-        "is-arrayish": "^0.2.1"
+        "enzyme-adapter-utils": "^1.12.0",
+        "object.assign": "^4.1.0",
+        "object.values": "^1.1.0",
+        "prop-types": "^15.7.2",
+        "react-is": "^16.8.6",
+        "react-test-renderer": "^16.0.0-0",
+        "semver": "^5.6.0"
       }
     },
-    "es-abstract": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
-      "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+    "enzyme-adapter-utils": {
+      "version": "1.12.0",
+      "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.0.tgz",
+      "integrity": "sha512-wkZvE0VxcFx/8ZsBw0iAbk3gR1d9hK447ebnSYBf95+r32ezBq+XDSAvRErkc4LZosgH8J7et7H7/7CtUuQfBA==",
+      "dev": true,
       "requires": {
-        "es-to-primitive": "^1.2.0",
+        "airbnb-prop-types": "^2.13.2",
+        "function.prototype.name": "^1.1.0",
+        "object.assign": "^4.1.0",
+        "object.fromentries": "^2.0.0",
+        "prop-types": "^15.7.2",
+        "semver": "^5.6.0"
+      }
+    },
+    "enzyme-to-json": {
+      "version": "3.3.5",
+      "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.3.5.tgz",
+      "integrity": "sha512-DmH1wJ68HyPqKSYXdQqB33ZotwfUhwQZW3IGXaNXgR69Iodaoj8TF/D9RjLdz4pEhGq2Tx2zwNUIjBuqoZeTgA==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.4"
+      }
+    },
+    "errno": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "dev": true,
+      "requires": {
+        "prr": "~1.0.1"
+      }
+    },
+    "error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "es-abstract": {
+      "version": "1.13.0",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+      "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+      "requires": {
+        "es-to-primitive": "^1.2.0",
         "function-bind": "^1.1.1",
         "has": "^1.0.3",
         "is-callable": "^1.1.4",
@@ -3130,14 +3424,6 @@
         "esutils": "^2.0.2",
         "optionator": "^0.8.1",
         "source-map": "~0.6.1"
-      },
-      "dependencies": {
-        "esprima": {
-          "version": "3.1.3",
-          "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
-          "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
-          "dev": true
-        }
       }
     },
     "eslint-scope": {
@@ -3151,9 +3437,9 @@
       }
     },
     "esprima": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+      "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
       "dev": true
     },
     "esrecurse": {
@@ -3184,9 +3470,9 @@
       "dev": true
     },
     "eventemitter3": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
-      "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
+      "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==",
       "dev": true
     },
     "events": {
@@ -3310,16 +3596,16 @@
       }
     },
     "expect": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/expect/-/expect-24.7.1.tgz",
-      "integrity": "sha512-mGfvMTPduksV3xoI0xur56pQsg2vJjNf5+a+bXOjqCkiCBbmCayrBbHS/75y9K430cfqyocPr2ZjiNiRx4SRKw==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/expect/-/expect-24.8.0.tgz",
+      "integrity": "sha512-/zYvP8iMDrzaaxHVa724eJBCKqSHmO0FA7EDkBiRHxg6OipmMn1fN+C8T9L9K8yr7UONkOifu6+LLH+z76CnaA==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "ansi-styles": "^3.2.0",
-        "jest-get-type": "^24.3.0",
-        "jest-matcher-utils": "^24.7.0",
-        "jest-message-util": "^24.7.1",
+        "jest-get-type": "^24.8.0",
+        "jest-matcher-utils": "^24.8.0",
+        "jest-message-util": "^24.8.0",
         "jest-regex-util": "^24.3.0"
       }
     },
@@ -3562,19 +3848,9 @@
       }
     },
     "file-saver": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.1.tgz",
-      "integrity": "sha512-dCB3K7/BvAcUmtmh1DzFdv0eXSVJ9IAFt1mw3XZfAexodNRoE29l3xB2EX4wH2q8m/UTzwzEPq/ArYk98kUkBQ=="
-    },
-    "fileset": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
-      "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
-      "dev": true,
-      "requires": {
-        "glob": "^7.0.3",
-        "minimatch": "^3.0.3"
-      }
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz",
+      "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw=="
     },
     "filesize": {
       "version": "3.6.1",
@@ -3711,6 +3987,38 @@
       "requires": {
         "inherits": "^2.0.3",
         "readable-stream": "^2.3.6"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "follow-redirects": {
@@ -3782,12 +4090,44 @@
       "requires": {
         "inherits": "^2.0.1",
         "readable-stream": "^2.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "fs-extra": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
-      "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.0.1.tgz",
+      "integrity": "sha512-W+XLrggcDzlle47X/XnS7FXrXu9sDo+Ze9zpndeBxdgv88FHLm1HtmkhEwavruS6koanBjp098rUpHs65EmG7A==",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.2",
@@ -3805,6 +4145,38 @@
         "iferr": "^0.1.5",
         "imurmurhash": "^0.1.4",
         "readable-stream": "1 || 2"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "fs.realpath": {
@@ -3814,9 +4186,9 @@
       "dev": true
     },
     "fsevents": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz",
-      "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==",
+      "version": "1.2.9",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
+      "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
       "dev": true,
       "optional": true,
       "requires": {
@@ -3833,8 +4205,7 @@
         "ansi-regex": {
           "version": "2.1.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -3855,14 +4226,12 @@
         "balanced-match": {
           "version": "1.0.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -3877,20 +4246,17 @@
         "code-point-at": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "concat-map": {
           "version": "0.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "console-control-strings": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -4007,8 +4373,7 @@
         "inherits": {
           "version": "2.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "ini": {
           "version": "1.3.5",
@@ -4020,7 +4385,6 @@
           "version": "1.0.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -4035,7 +4399,6 @@
           "version": "3.0.4",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
@@ -4043,14 +4406,12 @@
         "minimist": {
           "version": "0.0.8",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "minipass": {
           "version": "2.3.5",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.2",
             "yallist": "^3.0.0"
@@ -4069,7 +4430,6 @@
           "version": "0.5.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -4150,8 +4510,7 @@
         "number-is-nan": {
           "version": "1.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -4163,7 +4522,6 @@
           "version": "1.4.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -4249,8 +4607,7 @@
         "safe-buffer": {
           "version": "5.1.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -4286,7 +4643,6 @@
           "version": "1.0.2",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -4306,7 +4662,6 @@
           "version": "3.0.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -4350,21 +4705,19 @@
         "wrappy": {
           "version": "1.0.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "yallist": {
           "version": "3.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         }
       }
     },
     "fstream": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
-      "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.2",
@@ -4378,6 +4731,17 @@
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
       "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
     },
+    "function.prototype.name": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz",
+      "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "function-bind": "^1.1.1",
+        "is-callable": "^1.1.3"
+      }
+    },
     "gauge": {
       "version": "2.7.4",
       "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -4477,9 +4841,9 @@
       }
     },
     "glob": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+      "version": "7.1.4",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+      "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
       "dev": true,
       "requires": {
         "fs.realpath": "^1.0.0",
@@ -4538,9 +4902,9 @@
       }
     },
     "globals": {
-      "version": "11.11.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz",
-      "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==",
+      "version": "11.12.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
       "dev": true
     },
     "globby": {
@@ -4838,6 +5202,47 @@
         "obuf": "^1.0.0",
         "readable-stream": "^2.0.1",
         "wbuf": "^1.1.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
+      }
+    },
+    "html-element-map": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.0.1.tgz",
+      "integrity": "sha512-BZSfdEm6n706/lBfXKWa4frZRZcT5k1cOusw95ijZsHlI+GdgY0v95h6IzO3iIDf2ROwq570YTwqNPqHcNMozw==",
+      "dev": true,
+      "requires": {
+        "array-filter": "^1.0.0"
       }
     },
     "html-encoding-sniffer": {
@@ -4873,19 +5278,6 @@
         "entities": "^1.1.1",
         "inherits": "^2.0.1",
         "readable-stream": "^3.1.1"
-      },
-      "dependencies": {
-        "readable-stream": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz",
-          "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==",
-          "dev": true,
-          "requires": {
-            "inherits": "^2.0.3",
-            "string_decoder": "^1.1.1",
-            "util-deprecate": "^1.0.1"
-          }
-        }
       }
     },
     "http-deceiver": {
@@ -5177,9 +5569,9 @@
       }
     },
     "is-alphabetical": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz",
-      "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz",
+      "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==",
       "dev": true
     },
     "is-alphanumeric": {
@@ -5189,9 +5581,9 @@
       "dev": true
     },
     "is-alphanumerical": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz",
-      "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz",
+      "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==",
       "dev": true,
       "requires": {
         "is-alphabetical": "^1.0.0",
@@ -5213,6 +5605,12 @@
         "binary-extensions": "^1.0.0"
       }
     },
+    "is-boolean-object": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.0.tgz",
+      "integrity": "sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=",
+      "dev": true
+    },
     "is-buffer": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -5258,9 +5656,9 @@
       "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
     },
     "is-decimal": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz",
-      "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz",
+      "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==",
       "dev": true
     },
     "is-descriptor": {
@@ -5331,9 +5729,9 @@
       }
     },
     "is-hexadecimal": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz",
-      "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.3.tgz",
+      "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==",
       "dev": true
     },
     "is-number": {
@@ -5356,6 +5754,12 @@
         }
       }
     },
+    "is-number-object": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.3.tgz",
+      "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=",
+      "dev": true
+    },
     "is-obj": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
@@ -5420,6 +5824,18 @@
       "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
       "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
     },
+    "is-string": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz",
+      "integrity": "sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=",
+      "dev": true
+    },
+    "is-subset": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz",
+      "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=",
+      "dev": true
+    },
     "is-supported-regexp-flag": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz",
@@ -5447,9 +5863,9 @@
       "dev": true
     },
     "is-whitespace-character": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz",
-      "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.3.tgz",
+      "integrity": "sha512-SNPgMLz9JzPccD3nPctcj8sZlX9DAMJSKH8bP7Z6bohCwuNgX8xbWr1eTAYXX9Vpi/aSn8Y1akL9WgM3t43YNQ==",
       "dev": true
     },
     "is-windows": {
@@ -5459,9 +5875,9 @@
       "dev": true
     },
     "is-word-character": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz",
-      "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.3.tgz",
+      "integrity": "sha512-0wfcrFgOOOBdgRNT9H33xe6Zi6yhX/uoc4U8NBZGeQQB0ctU1dnlNTyL9JM2646bHDTpsDm1Brb3VPoCIMrd/A==",
       "dev": true
     },
     "is-wsl": {
@@ -5502,54 +5918,24 @@
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
       "dev": true
     },
-    "istanbul-api": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.5.tgz",
-      "integrity": "sha512-meYk1BwDp59Pfse1TvPrkKYgVqAufbdBLEVoqvu/hLLKSaQ054ZTksbNepyc223tMnWdm6AdK2URIJJRqdP87g==",
-      "dev": true,
-      "requires": {
-        "async": "^2.6.1",
-        "compare-versions": "^3.2.1",
-        "fileset": "^2.0.3",
-        "istanbul-lib-coverage": "^2.0.4",
-        "istanbul-lib-hook": "^2.0.6",
-        "istanbul-lib-instrument": "^3.2.0",
-        "istanbul-lib-report": "^2.0.7",
-        "istanbul-lib-source-maps": "^3.0.5",
-        "istanbul-reports": "^2.2.3",
-        "js-yaml": "^3.13.0",
-        "make-dir": "^2.1.0",
-        "minimatch": "^3.0.4",
-        "once": "^1.4.0"
-      }
-    },
     "istanbul-lib-coverage": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
-      "integrity": "sha512-LXTBICkMARVgo579kWDm8SqfB6nvSDKNqIOBEjmJRnL04JvoMHCYGWaMddQnseJYtkEuEvO/sIcOxPLk9gERug==",
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+      "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
       "dev": true
     },
-    "istanbul-lib-hook": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.6.tgz",
-      "integrity": "sha512-829DKONApZ7UCiPXcOYWSgkFXa4+vNYoNOt3F+4uDJLKL1OotAoVwvThoEj1i8jmOj7odbYcR3rnaHu+QroaXg==",
-      "dev": true,
-      "requires": {
-        "append-transform": "^1.0.0"
-      }
-    },
     "istanbul-lib-instrument": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.2.0.tgz",
-      "integrity": "sha512-06IM3xShbNW4NgZv5AP4QH0oHqf1/ivFo8eFys0ZjPXHGldHJQWb3riYOKXqmOqfxXBfxu4B+g/iuhOPZH0RJg==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+      "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
       "dev": true,
       "requires": {
-        "@babel/generator": "^7.0.0",
-        "@babel/parser": "^7.0.0",
-        "@babel/template": "^7.0.0",
-        "@babel/traverse": "^7.0.0",
-        "@babel/types": "^7.0.0",
-        "istanbul-lib-coverage": "^2.0.4",
+        "@babel/generator": "^7.4.0",
+        "@babel/parser": "^7.4.3",
+        "@babel/template": "^7.4.0",
+        "@babel/traverse": "^7.4.3",
+        "@babel/types": "^7.4.0",
+        "istanbul-lib-coverage": "^2.0.5",
         "semver": "^6.0.0"
       },
       "dependencies": {
@@ -5562,26 +5948,26 @@
       }
     },
     "istanbul-lib-report": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.7.tgz",
-      "integrity": "sha512-wLH6beJBFbRBLiTlMOBxmb85cnVM1Vyl36N48e4e/aTKSM3WbOx7zbVIH1SQ537fhhsPbX0/C5JB4qsmyRXXyA==",
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz",
+      "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==",
       "dev": true,
       "requires": {
-        "istanbul-lib-coverage": "^2.0.4",
+        "istanbul-lib-coverage": "^2.0.5",
         "make-dir": "^2.1.0",
-        "supports-color": "^6.0.0"
+        "supports-color": "^6.1.0"
       }
     },
     "istanbul-lib-source-maps": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.5.tgz",
-      "integrity": "sha512-eDhZ7r6r1d1zQPVZehLc3D0K14vRba/eBYkz3rw16DLOrrTzve9RmnkcwrrkWVgO1FL3EK5knujVe5S8QHE9xw==",
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz",
+      "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==",
       "dev": true,
       "requires": {
         "debug": "^4.1.1",
-        "istanbul-lib-coverage": "^2.0.4",
+        "istanbul-lib-coverage": "^2.0.5",
         "make-dir": "^2.1.0",
-        "rimraf": "^2.6.2",
+        "rimraf": "^2.6.3",
         "source-map": "^0.6.1"
       },
       "dependencies": {
@@ -5597,40 +5983,40 @@
       }
     },
     "istanbul-reports": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.3.tgz",
-      "integrity": "sha512-T6EbPuc8Cb620LWAYyZ4D8SSn06dY9i1+IgUX2lTH8gbwflMc9Obd33zHTyNX653ybjpamAHS9toKS3E6cGhTw==",
+      "version": "2.2.6",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz",
+      "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==",
       "dev": true,
       "requires": {
-        "handlebars": "^4.1.0"
+        "handlebars": "^4.1.2"
       }
     },
     "jest": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest/-/jest-24.7.1.tgz",
-      "integrity": "sha512-AbvRar5r++izmqo5gdbAjTeA6uNRGoNRuj5vHB0OnDXo2DXWZJVuaObiGgtlvhKb+cWy2oYbQSfxv7Q7GjnAtA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest/-/jest-24.8.0.tgz",
+      "integrity": "sha512-o0HM90RKFRNWmAWvlyV8i5jGZ97pFwkeVoGvPW1EtLTgJc2+jcuqcbbqcSZLE/3f2S5pt0y2ZBETuhpWNl1Reg==",
       "dev": true,
       "requires": {
         "import-local": "^2.0.0",
-        "jest-cli": "^24.7.1"
+        "jest-cli": "^24.8.0"
       },
       "dependencies": {
         "jest-cli": {
-          "version": "24.7.1",
-          "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.7.1.tgz",
-          "integrity": "sha512-32OBoSCVPzcTslGFl6yVCMzB2SqX3IrWwZCY5mZYkb0D2WsogmU3eV2o8z7+gRQa4o4sZPX/k7GU+II7CxM6WQ==",
+          "version": "24.8.0",
+          "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.8.0.tgz",
+          "integrity": "sha512-+p6J00jSMPQ116ZLlHJJvdf8wbjNbZdeSX9ptfHX06/MSNaXmKihQzx5vQcw0q2G6JsdVkUIdWbOWtSnaYs3yA==",
           "dev": true,
           "requires": {
-            "@jest/core": "^24.7.1",
-            "@jest/test-result": "^24.7.1",
-            "@jest/types": "^24.7.0",
+            "@jest/core": "^24.8.0",
+            "@jest/test-result": "^24.8.0",
+            "@jest/types": "^24.8.0",
             "chalk": "^2.0.1",
             "exit": "^0.1.2",
             "import-local": "^2.0.0",
             "is-ci": "^2.0.0",
-            "jest-config": "^24.7.1",
-            "jest-util": "^24.7.1",
-            "jest-validate": "^24.7.0",
+            "jest-config": "^24.8.0",
+            "jest-util": "^24.8.0",
+            "jest-validate": "^24.8.0",
             "prompts": "^2.0.1",
             "realpath-native": "^1.1.0",
             "yargs": "^12.0.2"
@@ -5639,51 +6025,51 @@
       }
     },
     "jest-changed-files": {
-      "version": "24.7.0",
-      "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.7.0.tgz",
-      "integrity": "sha512-33BgewurnwSfJrW7T5/ZAXGE44o7swLslwh8aUckzq2e17/2Os1V0QU506ZNik3hjs8MgnEMKNkcud442NCDTw==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.8.0.tgz",
+      "integrity": "sha512-qgANC1Yrivsq+UrLXsvJefBKVoCsKB0Hv+mBb6NMjjZ90wwxCDmU3hsCXBya30cH+LnPYjwgcU65i6yJ5Nfuug==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "execa": "^1.0.0",
         "throat": "^4.0.0"
       }
     },
     "jest-config": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.7.1.tgz",
-      "integrity": "sha512-8FlJNLI+X+MU37j7j8RE4DnJkvAghXmBWdArVzypW6WxfGuxiL/CCkzBg0gHtXhD2rxla3IMOSUAHylSKYJ83g==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.8.0.tgz",
+      "integrity": "sha512-Czl3Nn2uEzVGsOeaewGWoDPD8GStxCpAe0zOYs2x2l0fZAgPbCr3uwUkgNKV3LwE13VXythM946cd5rdGkkBZw==",
       "dev": true,
       "requires": {
         "@babel/core": "^7.1.0",
-        "@jest/test-sequencer": "^24.7.1",
-        "@jest/types": "^24.7.0",
-        "babel-jest": "^24.7.1",
+        "@jest/test-sequencer": "^24.8.0",
+        "@jest/types": "^24.8.0",
+        "babel-jest": "^24.8.0",
         "chalk": "^2.0.1",
         "glob": "^7.1.1",
-        "jest-environment-jsdom": "^24.7.1",
-        "jest-environment-node": "^24.7.1",
-        "jest-get-type": "^24.3.0",
-        "jest-jasmine2": "^24.7.1",
+        "jest-environment-jsdom": "^24.8.0",
+        "jest-environment-node": "^24.8.0",
+        "jest-get-type": "^24.8.0",
+        "jest-jasmine2": "^24.8.0",
         "jest-regex-util": "^24.3.0",
-        "jest-resolve": "^24.7.1",
-        "jest-util": "^24.7.1",
-        "jest-validate": "^24.7.0",
+        "jest-resolve": "^24.8.0",
+        "jest-util": "^24.8.0",
+        "jest-validate": "^24.8.0",
         "micromatch": "^3.1.10",
-        "pretty-format": "^24.7.0",
+        "pretty-format": "^24.8.0",
         "realpath-native": "^1.1.0"
       }
     },
     "jest-diff": {
-      "version": "24.7.0",
-      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz",
-      "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.8.0.tgz",
+      "integrity": "sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g==",
       "dev": true,
       "requires": {
         "chalk": "^2.0.1",
         "diff-sequences": "^24.3.0",
-        "jest-get-type": "^24.3.0",
-        "pretty-format": "^24.7.0"
+        "jest-get-type": "^24.8.0",
+        "pretty-format": "^24.8.0"
       }
     },
     "jest-docblock": {
@@ -5696,65 +6082,65 @@
       }
     },
     "jest-each": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.7.1.tgz",
-      "integrity": "sha512-4fsS8fEfLa3lfnI1Jw6NxjhyRTgfpuOVTeUZZFyVYqeTa4hPhr2YkToUhouuLTrL2eMGOfpbdMyRx0GQ/VooKA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.8.0.tgz",
+      "integrity": "sha512-NrwK9gaL5+XgrgoCsd9svsoWdVkK4gnvyhcpzd6m487tXHqIdYeykgq3MKI1u4I+5Zf0tofr70at9dWJDeb+BA==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "chalk": "^2.0.1",
-        "jest-get-type": "^24.3.0",
-        "jest-util": "^24.7.1",
-        "pretty-format": "^24.7.0"
+        "jest-get-type": "^24.8.0",
+        "jest-util": "^24.8.0",
+        "pretty-format": "^24.8.0"
       }
     },
     "jest-environment-jsdom": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.7.1.tgz",
-      "integrity": "sha512-Gnhb+RqE2JuQGb3kJsLF8vfqjt3PHKSstq4Xc8ic+ax7QKo4Z0RWGucU3YV+DwKR3T9SYc+3YCUQEJs8r7+Jxg==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.8.0.tgz",
+      "integrity": "sha512-qbvgLmR7PpwjoFjM/sbuqHJt/NCkviuq9vus9NBn/76hhSidO+Z6Bn9tU8friecegbJL8gzZQEMZBQlFWDCwAQ==",
       "dev": true,
       "requires": {
-        "@jest/environment": "^24.7.1",
-        "@jest/fake-timers": "^24.7.1",
-        "@jest/types": "^24.7.0",
-        "jest-mock": "^24.7.0",
-        "jest-util": "^24.7.1",
+        "@jest/environment": "^24.8.0",
+        "@jest/fake-timers": "^24.8.0",
+        "@jest/types": "^24.8.0",
+        "jest-mock": "^24.8.0",
+        "jest-util": "^24.8.0",
         "jsdom": "^11.5.1"
       }
     },
     "jest-environment-node": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.7.1.tgz",
-      "integrity": "sha512-GJJQt1p9/C6aj6yNZMvovZuxTUd+BEJprETdvTKSb4kHcw4mFj8777USQV0FJoJ4V3djpOwA5eWyPwfq//PFBA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.8.0.tgz",
+      "integrity": "sha512-vIGUEScd1cdDgR6sqn2M08sJTRLQp6Dk/eIkCeO4PFHxZMOgy+uYLPMC4ix3PEfM5Au/x3uQ/5Tl0DpXXZsJ/Q==",
       "dev": true,
       "requires": {
-        "@jest/environment": "^24.7.1",
-        "@jest/fake-timers": "^24.7.1",
-        "@jest/types": "^24.7.0",
-        "jest-mock": "^24.7.0",
-        "jest-util": "^24.7.1"
+        "@jest/environment": "^24.8.0",
+        "@jest/fake-timers": "^24.8.0",
+        "@jest/types": "^24.8.0",
+        "jest-mock": "^24.8.0",
+        "jest-util": "^24.8.0"
       }
     },
     "jest-get-type": {
-      "version": "24.3.0",
-      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz",
-      "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.8.0.tgz",
+      "integrity": "sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ==",
       "dev": true
     },
     "jest-haste-map": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.7.1.tgz",
-      "integrity": "sha512-g0tWkzjpHD2qa03mTKhlydbmmYiA2KdcJe762SbfFo/7NIMgBWAA0XqQlApPwkWOF7Cxoi/gUqL0i6DIoLpMBw==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.8.0.tgz",
+      "integrity": "sha512-ZBPRGHdPt1rHajWelXdqygIDpJx8u3xOoLyUBWRW28r3tagrgoepPrzAozW7kW9HrQfhvmiv1tncsxqHJO1onQ==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "anymatch": "^2.0.0",
         "fb-watchman": "^2.0.0",
         "fsevents": "^1.2.7",
         "graceful-fs": "^4.1.15",
         "invariant": "^2.2.4",
         "jest-serializer": "^24.4.0",
-        "jest-util": "^24.7.1",
+        "jest-util": "^24.8.0",
         "jest-worker": "^24.6.0",
         "micromatch": "^3.1.10",
         "sane": "^4.0.3",
@@ -5762,59 +6148,59 @@
       }
     },
     "jest-jasmine2": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.7.1.tgz",
-      "integrity": "sha512-Y/9AOJDV1XS44wNwCaThq4Pw3gBPiOv/s6NcbOAkVRRUEPu+36L2xoPsqQXsDrxoBerqeyslpn2TpCI8Zr6J2w==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.8.0.tgz",
+      "integrity": "sha512-cEky88npEE5LKd5jPpTdDCLvKkdyklnaRycBXL6GNmpxe41F0WN44+i7lpQKa/hcbXaQ+rc9RMaM4dsebrYong==",
       "dev": true,
       "requires": {
         "@babel/traverse": "^7.1.0",
-        "@jest/environment": "^24.7.1",
-        "@jest/test-result": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/environment": "^24.8.0",
+        "@jest/test-result": "^24.8.0",
+        "@jest/types": "^24.8.0",
         "chalk": "^2.0.1",
         "co": "^4.6.0",
-        "expect": "^24.7.1",
+        "expect": "^24.8.0",
         "is-generator-fn": "^2.0.0",
-        "jest-each": "^24.7.1",
-        "jest-matcher-utils": "^24.7.0",
-        "jest-message-util": "^24.7.1",
-        "jest-runtime": "^24.7.1",
-        "jest-snapshot": "^24.7.1",
-        "jest-util": "^24.7.1",
-        "pretty-format": "^24.7.0",
+        "jest-each": "^24.8.0",
+        "jest-matcher-utils": "^24.8.0",
+        "jest-message-util": "^24.8.0",
+        "jest-runtime": "^24.8.0",
+        "jest-snapshot": "^24.8.0",
+        "jest-util": "^24.8.0",
+        "pretty-format": "^24.8.0",
         "throat": "^4.0.0"
       }
     },
     "jest-leak-detector": {
-      "version": "24.7.0",
-      "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.7.0.tgz",
-      "integrity": "sha512-zV0qHKZGXtmPVVzT99CVEcHE9XDf+8LwiE0Ob7jjezERiGVljmqKFWpV2IkG+rkFIEUHFEkMiICu7wnoPM/RoQ==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.8.0.tgz",
+      "integrity": "sha512-cG0yRSK8A831LN8lIHxI3AblB40uhv0z+SsQdW3GoMMVcK+sJwrIIyax5tu3eHHNJ8Fu6IMDpnLda2jhn2pD/g==",
       "dev": true,
       "requires": {
-        "pretty-format": "^24.7.0"
+        "pretty-format": "^24.8.0"
       }
     },
     "jest-matcher-utils": {
-      "version": "24.7.0",
-      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz",
-      "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz",
+      "integrity": "sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw==",
       "dev": true,
       "requires": {
         "chalk": "^2.0.1",
-        "jest-diff": "^24.7.0",
-        "jest-get-type": "^24.3.0",
-        "pretty-format": "^24.7.0"
+        "jest-diff": "^24.8.0",
+        "jest-get-type": "^24.8.0",
+        "pretty-format": "^24.8.0"
       }
     },
     "jest-message-util": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz",
-      "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.8.0.tgz",
+      "integrity": "sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
-        "@jest/test-result": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/test-result": "^24.8.0",
+        "@jest/types": "^24.8.0",
         "@types/stack-utils": "^1.0.1",
         "chalk": "^2.0.1",
         "micromatch": "^3.1.10",
@@ -5823,12 +6209,12 @@
       }
     },
     "jest-mock": {
-      "version": "24.7.0",
-      "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.7.0.tgz",
-      "integrity": "sha512-6taW4B4WUcEiT2V9BbOmwyGuwuAFT2G8yghF7nyNW1/2gq5+6aTqSPcS9lS6ArvEkX55vbPAS/Jarx5LSm4Fng==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.8.0.tgz",
+      "integrity": "sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0"
+        "@jest/types": "^24.8.0"
       }
     },
     "jest-pnp-resolver": {
@@ -5844,12 +6230,12 @@
       "dev": true
     },
     "jest-resolve": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.7.1.tgz",
-      "integrity": "sha512-Bgrc+/UUZpGJ4323sQyj85hV9d+ANyPNu6XfRDUcyFNX1QrZpSoM0kE4Mb2vZMAYTJZsBFzYe8X1UaOkOELSbw==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.8.0.tgz",
+      "integrity": "sha512-+hjSzi1PoRvnuOICoYd5V/KpIQmkAsfjFO71458hQ2Whi/yf1GDeBOFj8Gxw4LrApHsVJvn5fmjcPdmoUHaVKw==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "browser-resolve": "^1.11.3",
         "chalk": "^2.0.1",
         "jest-pnp-resolver": "^1.2.1",
@@ -5857,68 +6243,68 @@
       }
     },
     "jest-resolve-dependencies": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.7.1.tgz",
-      "integrity": "sha512-2Eyh5LJB2liNzfk4eo7bD1ZyBbqEJIyyrFtZG555cSWW9xVHxII2NuOkSl1yUYTAYCAmM2f2aIT5A7HzNmubyg==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.8.0.tgz",
+      "integrity": "sha512-hyK1qfIf/krV+fSNyhyJeq3elVMhK9Eijlwy+j5jqmZ9QsxwKBiP6qukQxaHtK8k6zql/KYWwCTQ+fDGTIJauw==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "jest-regex-util": "^24.3.0",
-        "jest-snapshot": "^24.7.1"
+        "jest-snapshot": "^24.8.0"
       }
     },
     "jest-runner": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.7.1.tgz",
-      "integrity": "sha512-aNFc9liWU/xt+G9pobdKZ4qTeG/wnJrJna3VqunziDNsWT3EBpmxXZRBMKCsNMyfy+A/XHiV+tsMLufdsNdgCw==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.8.0.tgz",
+      "integrity": "sha512-utFqC5BaA3JmznbissSs95X1ZF+d+4WuOWwpM9+Ak356YtMhHE/GXUondZdcyAAOTBEsRGAgH/0TwLzfI9h7ow==",
       "dev": true,
       "requires": {
         "@jest/console": "^24.7.1",
-        "@jest/environment": "^24.7.1",
-        "@jest/test-result": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/environment": "^24.8.0",
+        "@jest/test-result": "^24.8.0",
+        "@jest/types": "^24.8.0",
         "chalk": "^2.4.2",
         "exit": "^0.1.2",
         "graceful-fs": "^4.1.15",
-        "jest-config": "^24.7.1",
+        "jest-config": "^24.8.0",
         "jest-docblock": "^24.3.0",
-        "jest-haste-map": "^24.7.1",
-        "jest-jasmine2": "^24.7.1",
-        "jest-leak-detector": "^24.7.0",
-        "jest-message-util": "^24.7.1",
-        "jest-resolve": "^24.7.1",
-        "jest-runtime": "^24.7.1",
-        "jest-util": "^24.7.1",
+        "jest-haste-map": "^24.8.0",
+        "jest-jasmine2": "^24.8.0",
+        "jest-leak-detector": "^24.8.0",
+        "jest-message-util": "^24.8.0",
+        "jest-resolve": "^24.8.0",
+        "jest-runtime": "^24.8.0",
+        "jest-util": "^24.8.0",
         "jest-worker": "^24.6.0",
         "source-map-support": "^0.5.6",
         "throat": "^4.0.0"
       }
     },
     "jest-runtime": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.7.1.tgz",
-      "integrity": "sha512-0VAbyBy7tll3R+82IPJpf6QZkokzXPIS71aDeqh+WzPRXRCNz6StQ45otFariPdJ4FmXpDiArdhZrzNAC3sj6A==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.8.0.tgz",
+      "integrity": "sha512-Mq0aIXhvO/3bX44ccT+czU1/57IgOMyy80oM0XR/nyD5zgBcesF84BPabZi39pJVA6UXw+fY2Q1N+4BiVUBWOA==",
       "dev": true,
       "requires": {
         "@jest/console": "^24.7.1",
-        "@jest/environment": "^24.7.1",
+        "@jest/environment": "^24.8.0",
         "@jest/source-map": "^24.3.0",
-        "@jest/transform": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/transform": "^24.8.0",
+        "@jest/types": "^24.8.0",
         "@types/yargs": "^12.0.2",
         "chalk": "^2.0.1",
         "exit": "^0.1.2",
         "glob": "^7.1.3",
         "graceful-fs": "^4.1.15",
-        "jest-config": "^24.7.1",
-        "jest-haste-map": "^24.7.1",
-        "jest-message-util": "^24.7.1",
-        "jest-mock": "^24.7.0",
+        "jest-config": "^24.8.0",
+        "jest-haste-map": "^24.8.0",
+        "jest-message-util": "^24.8.0",
+        "jest-mock": "^24.8.0",
         "jest-regex-util": "^24.3.0",
-        "jest-resolve": "^24.7.1",
-        "jest-snapshot": "^24.7.1",
-        "jest-util": "^24.7.1",
-        "jest-validate": "^24.7.0",
+        "jest-resolve": "^24.8.0",
+        "jest-snapshot": "^24.8.0",
+        "jest-util": "^24.8.0",
+        "jest-validate": "^24.8.0",
         "realpath-native": "^1.1.0",
         "slash": "^2.0.0",
         "strip-bom": "^3.0.0",
@@ -5932,36 +6318,36 @@
       "dev": true
     },
     "jest-snapshot": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.7.1.tgz",
-      "integrity": "sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.8.0.tgz",
+      "integrity": "sha512-5ehtWoc8oU9/cAPe6fez6QofVJLBKyqkY2+TlKTOf0VllBB/mqUNdARdcjlZrs9F1Cv+/HKoCS/BknT0+tmfPg==",
       "dev": true,
       "requires": {
         "@babel/types": "^7.0.0",
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "chalk": "^2.0.1",
-        "expect": "^24.7.1",
-        "jest-diff": "^24.7.0",
-        "jest-matcher-utils": "^24.7.0",
-        "jest-message-util": "^24.7.1",
-        "jest-resolve": "^24.7.1",
+        "expect": "^24.8.0",
+        "jest-diff": "^24.8.0",
+        "jest-matcher-utils": "^24.8.0",
+        "jest-message-util": "^24.8.0",
+        "jest-resolve": "^24.8.0",
         "mkdirp": "^0.5.1",
         "natural-compare": "^1.4.0",
-        "pretty-format": "^24.7.0",
+        "pretty-format": "^24.8.0",
         "semver": "^5.5.0"
       }
     },
     "jest-util": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.7.1.tgz",
-      "integrity": "sha512-/KilOue2n2rZ5AnEBYoxOXkeTu6vi7cjgQ8MXEkih0oeAXT6JkS3fr7/j8+engCjciOU1Nq5loMSKe0A1oeX0A==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.8.0.tgz",
+      "integrity": "sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA==",
       "dev": true,
       "requires": {
         "@jest/console": "^24.7.1",
-        "@jest/fake-timers": "^24.7.1",
+        "@jest/fake-timers": "^24.8.0",
         "@jest/source-map": "^24.3.0",
-        "@jest/test-result": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/test-result": "^24.8.0",
+        "@jest/types": "^24.8.0",
         "callsites": "^3.0.0",
         "chalk": "^2.0.1",
         "graceful-fs": "^4.1.15",
@@ -5972,31 +6358,31 @@
       }
     },
     "jest-validate": {
-      "version": "24.7.0",
-      "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.7.0.tgz",
-      "integrity": "sha512-cgai/gts9B2chz1rqVdmLhzYxQbgQurh1PEQSvSgPZ8KGa1AqXsqC45W5wKEwzxKrWqypuQrQxnF4+G9VejJJA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.8.0.tgz",
+      "integrity": "sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "camelcase": "^5.0.0",
         "chalk": "^2.0.1",
-        "jest-get-type": "^24.3.0",
+        "jest-get-type": "^24.8.0",
         "leven": "^2.1.0",
-        "pretty-format": "^24.7.0"
+        "pretty-format": "^24.8.0"
       }
     },
     "jest-watcher": {
-      "version": "24.7.1",
-      "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.7.1.tgz",
-      "integrity": "sha512-Wd6TepHLRHVKLNPacEsBwlp9raeBIO+01xrN24Dek4ggTS8HHnOzYSFnvp+6MtkkJ3KfMzy220KTi95e2rRkrw==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.8.0.tgz",
+      "integrity": "sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw==",
       "dev": true,
       "requires": {
-        "@jest/test-result": "^24.7.1",
-        "@jest/types": "^24.7.0",
+        "@jest/test-result": "^24.8.0",
+        "@jest/types": "^24.8.0",
         "@types/yargs": "^12.0.9",
         "ansi-escapes": "^3.0.0",
         "chalk": "^2.0.1",
-        "jest-util": "^24.7.1",
+        "jest-util": "^24.8.0",
         "string-length": "^2.0.0"
       }
     },
@@ -6029,6 +6415,14 @@
       "requires": {
         "argparse": "^1.0.7",
         "esprima": "^4.0.0"
+      },
+      "dependencies": {
+        "esprima": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+          "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+          "dev": true
+        }
       }
     },
     "jsbn": {
@@ -6069,6 +6463,14 @@
         "whatwg-url": "^6.4.1",
         "ws": "^5.2.0",
         "xml-name-validator": "^3.0.0"
+      },
+      "dependencies": {
+        "parse5": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
+          "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
+          "dev": true
+        }
       }
     },
     "jsesc": {
@@ -6261,23 +6663,23 @@
       "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
       "dev": true
     },
-    "lodash.assign": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
-      "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
-      "dev": true
-    },
-    "lodash.clonedeep": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
-      "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
-      "dev": true
-    },
     "lodash.debounce": {
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
       "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
     },
+    "lodash.escape": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
+      "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=",
+      "dev": true
+    },
+    "lodash.flattendeep": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+      "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
+      "dev": true
+    },
     "lodash.get": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
@@ -6288,12 +6690,6 @@
       "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
       "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
     },
-    "lodash.mergewith": {
-      "version": "4.6.1",
-      "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
-      "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==",
-      "dev": true
-    },
     "lodash.sortby": {
       "version": "4.7.0",
       "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -6341,9 +6737,9 @@
       "dev": true
     },
     "longest-streak": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz",
-      "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.3.tgz",
+      "integrity": "sha512-9lz5IVdpwsKLMzQi0MQ+oD9EA0mIGcWYP7jXMTZVXP8D42PwuAk+M/HBFYQoxt1G5OR8m7aSIgb1UymfWGBWEw==",
       "dev": true
     },
     "loose-envify": {
@@ -6444,21 +6840,21 @@
       }
     },
     "markdown-escapes": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz",
-      "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.3.tgz",
+      "integrity": "sha512-XUi5HJhhV5R74k8/0H2oCbCiYf/u4cO/rX8tnGkRvrqhsr5BRNU6Mg0yt/8UIx1iIS8220BNJsDb7XnILhLepw==",
       "dev": true
     },
     "markdown-table": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz",
-      "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz",
+      "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==",
       "dev": true
     },
     "mathml-tag-names": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz",
-      "integrity": "sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg==",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz",
+      "integrity": "sha512-pWB896KPGSGkp1XtyzRBftpTzwSOL0Gfk0wLvxt4f2mgzjY19o0LxJ3U25vNWTzsh7da+KTbuXQoQ3lOJZ8WHw==",
       "dev": true
     },
     "md5.js": {
@@ -6506,6 +6902,38 @@
       "requires": {
         "errno": "^0.1.3",
         "readable-stream": "^2.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "meow": {
@@ -6629,6 +7057,38 @@
       "dev": true,
       "requires": {
         "readable-stream": "^2.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "merge2": {
@@ -6812,6 +7272,12 @@
         }
       }
     },
+    "moo": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz",
+      "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==",
+      "dev": true
+    },
     "move-concurrently": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -6848,9 +7314,9 @@
       "dev": true
     },
     "nan": {
-      "version": "2.13.2",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
-      "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==",
+      "version": "2.14.0",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+      "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
       "dev": true
     },
     "nanomatch": {
@@ -6878,16 +7344,29 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
+    "nearley": {
+      "version": "2.16.0",
+      "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.16.0.tgz",
+      "integrity": "sha512-Tr9XD3Vt/EujXbZBv6UAHYoLUSMQAxSsTnm9K3koXzjzNWY195NqALeyrzLZBKzAkL3gl92BcSogqrHjD8QuUg==",
+      "dev": true,
+      "requires": {
+        "commander": "^2.19.0",
+        "moo": "^0.4.3",
+        "railroad-diagrams": "^1.0.0",
+        "randexp": "0.4.6",
+        "semver": "^5.4.1"
+      }
+    },
     "negotiator": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
-      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+      "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
       "dev": true
     },
     "neo-async": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz",
-      "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
+      "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
       "dev": true
     },
     "nice-try": {
@@ -6985,11 +7464,43 @@
         "vm-browserify": "0.0.4"
       },
       "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
         "punycode": {
           "version": "1.4.1",
           "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
           "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
           "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          },
+          "dependencies": {
+            "string_decoder": {
+              "version": "1.1.1",
+              "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+              "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+              "dev": true,
+              "requires": {
+                "safe-buffer": "~5.1.0"
+              }
+            }
+          }
         }
       }
     },
@@ -7013,18 +7524,18 @@
       }
     },
     "node-releases": {
-      "version": "1.1.15",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.15.tgz",
-      "integrity": "sha512-cKV097BQaZr8LTSRUa2+oc/aX5L8UkZtPQrMSTgiJEeaW7ymTDCoRaGCoaTqk0lqnalcoSHu4wjSl0Cmj2+bMw==",
+      "version": "1.1.19",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.19.tgz",
+      "integrity": "sha512-SH/B4WwovHbulIALsQllAVwqZZD1kPmKCqrhGfR29dXjLAVZMHvBjD3S6nL9D/J9QkmZ1R92/0wCMDKXUUvyyA==",
       "dev": true,
       "requires": {
         "semver": "^5.3.0"
       }
     },
     "node-sass": {
-      "version": "4.11.0",
-      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz",
-      "integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==",
+      "version": "4.12.0",
+      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz",
+      "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==",
       "dev": true,
       "requires": {
         "async-foreach": "^0.1.3",
@@ -7034,12 +7545,10 @@
         "get-stdin": "^4.0.1",
         "glob": "^7.0.3",
         "in-publish": "^2.0.0",
-        "lodash.assign": "^4.2.0",
-        "lodash.clonedeep": "^4.3.2",
-        "lodash.mergewith": "^4.6.0",
+        "lodash": "^4.17.11",
         "meow": "^3.7.0",
         "mkdirp": "^0.5.1",
-        "nan": "^2.10.0",
+        "nan": "^2.13.2",
         "node-gyp": "^3.8.0",
         "npmlog": "^4.0.0",
         "request": "^2.88.0",
@@ -7182,6 +7691,15 @@
         "set-blocking": "~2.0.0"
       }
     },
+    "nth-check": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+      "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+      "dev": true,
+      "requires": {
+        "boolbase": "~1.0.0"
+      }
+    },
     "num2fraction": {
       "version": "1.2.2",
       "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
@@ -7200,9 +7718,9 @@
       "integrity": "sha1-StCAk21EPCVhrtnyGX7//iX05QY="
     },
     "nwsapi": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.3.tgz",
-      "integrity": "sha512-RowAaJGEgYXEZfQ7tvvdtAQUKPyTR6T6wNu0fwlNsGQYr/h3yQc6oI8WnVZh3Y/Sylwc+dtAlvPqfFZjhTyk3A==",
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz",
+      "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==",
       "dev": true
     },
     "oauth-sign": {
@@ -7247,6 +7765,18 @@
         }
       }
     },
+    "object-inspect": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
+      "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
+      "dev": true
+    },
+    "object-is": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz",
+      "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=",
+      "dev": true
+    },
     "object-keys": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -7261,6 +7791,18 @@
         "isobject": "^3.0.0"
       }
     },
+    "object.assign": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+      "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "function-bind": "^1.1.1",
+        "has-symbols": "^1.0.0",
+        "object-keys": "^1.0.11"
+      }
+    },
     "object.entries": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
@@ -7272,6 +7814,18 @@
         "has": "^1.0.3"
       }
     },
+    "object.fromentries": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz",
+      "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "es-abstract": "^1.11.0",
+        "function-bind": "^1.1.1",
+        "has": "^1.0.1"
+      }
+    },
     "object.getownpropertydescriptors": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
@@ -7512,6 +8066,38 @@
         "cyclist": "~0.2.2",
         "inherits": "^2.0.3",
         "readable-stream": "^2.1.5"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "parse-asn1": {
@@ -7529,9 +8115,9 @@
       }
     },
     "parse-entities": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.1.tgz",
-      "integrity": "sha512-NBWYLQm1KSoDKk7GAHyioLTvCZ5QjdH/ASBBQTD3iLiAWJXS5bg1jEWI8nIJ+vgVvsceBVBcDGRWSo0KVQBvvg==",
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz",
+      "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==",
       "dev": true,
       "requires": {
         "character-entities": "^1.0.0",
@@ -7559,10 +8145,13 @@
       "dev": true
     },
     "parse5": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
-      "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
-      "dev": true
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+      "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*"
+      }
     },
     "parseurl": {
       "version": "1.3.3",
@@ -7715,12 +8304,6 @@
         "mkdirp": "0.5.x"
       },
       "dependencies": {
-        "async": {
-          "version": "1.5.2",
-          "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
-          "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
-          "dev": true
-        },
         "debug": {
           "version": "2.6.9",
           "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -7745,9 +8328,9 @@
       "dev": true
     },
     "postcss": {
-      "version": "7.0.14",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz",
-      "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==",
+      "version": "7.0.16",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz",
+      "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==",
       "dev": true,
       "requires": {
         "chalk": "^2.4.2",
@@ -7804,6 +8387,17 @@
         "yargs": "^12.0.1"
       },
       "dependencies": {
+        "fs-extra": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+          "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "jsonfile": "^4.0.0",
+            "universalify": "^0.1.0"
+          }
+        },
         "get-stdin": {
           "version": "6.0.0",
           "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
@@ -8378,12 +8972,12 @@
       "dev": true
     },
     "pretty-format": {
-      "version": "24.7.0",
-      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz",
-      "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==",
+      "version": "24.8.0",
+      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.8.0.tgz",
+      "integrity": "sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw==",
       "dev": true,
       "requires": {
-        "@jest/types": "^24.7.0",
+        "@jest/types": "^24.8.0",
         "ansi-regex": "^4.0.0",
         "ansi-styles": "^3.2.0",
         "react-is": "^16.8.4"
@@ -8441,6 +9035,17 @@
         "react-is": "^16.8.1"
       }
     },
+    "prop-types-exact": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz",
+      "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.3",
+        "object.assign": "^4.1.0",
+        "reflect.ownkeys": "^0.2.0"
+      }
+    },
     "proxy-addr": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
@@ -8552,6 +9157,31 @@
       "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=",
       "dev": true
     },
+    "raf": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
+      "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+      "dev": true,
+      "requires": {
+        "performance-now": "^2.1.0"
+      }
+    },
+    "railroad-diagrams": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
+      "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=",
+      "dev": true
+    },
+    "randexp": {
+      "version": "0.4.6",
+      "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
+      "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
+      "dev": true,
+      "requires": {
+        "discontinuous-range": "1.0.0",
+        "ret": "~0.1.10"
+      }
+    },
     "randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -8572,9 +9202,9 @@
       }
     },
     "range-parser": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
-      "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
       "dev": true
     },
     "raw-body": {
@@ -8705,6 +9335,28 @@
         "classnames": "^2.2.5"
       }
     },
+    "react-test-renderer": {
+      "version": "16.8.6",
+      "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.8.6.tgz",
+      "integrity": "sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==",
+      "dev": true,
+      "requires": {
+        "object-assign": "^4.1.1",
+        "prop-types": "^15.6.2",
+        "react-is": "^16.8.6",
+        "scheduler": "^0.13.6"
+      }
+    },
+    "react-testing-library": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/react-testing-library/-/react-testing-library-7.0.0.tgz",
+      "integrity": "sha512-8SHqwG+uhN9VhAgNVkVa3f7VjTw/L5CIaoAxKmy+EZuDQ6O+VsfcpRAyUw3MDL1h8S/gGrEiazmHBVL/uXsftA==",
+      "dev": true,
+      "requires": {
+        "@babel/runtime": "^7.4.3",
+        "dom-testing-library": "^4.0.0"
+      }
+    },
     "react-transition-group": {
       "version": "2.9.0",
       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
@@ -8791,26 +9443,14 @@
       }
     },
     "readable-stream": {
-      "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
-      "dev": true,
-      "requires": {
-        "core-util-is": "~1.0.0",
-        "inherits": "~2.0.3",
-        "isarray": "~1.0.0",
-        "process-nextick-args": "~2.0.0",
-        "safe-buffer": "~5.1.1",
-        "string_decoder": "~1.1.1",
-        "util-deprecate": "~1.0.1"
-      },
-      "dependencies": {
-        "isarray": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-          "dev": true
-        }
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz",
+      "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
       }
     },
     "readdir-scoped-modules": {
@@ -8834,6 +9474,38 @@
         "graceful-fs": "^4.1.11",
         "micromatch": "^3.1.10",
         "readable-stream": "^2.0.2"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "realpath-native": {
@@ -8855,6 +9527,12 @@
         "strip-indent": "^1.0.1"
       }
     },
+    "reflect.ownkeys": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz",
+      "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=",
+      "dev": true
+    },
     "regenerator-runtime": {
       "version": "0.13.2",
       "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
@@ -9055,9 +9733,9 @@
       "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
     },
     "resolve": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
-      "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz",
+      "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==",
       "dev": true,
       "requires": {
         "path-parse": "^1.0.6"
@@ -9150,6 +9828,16 @@
         "inherits": "^2.0.1"
       }
     },
+    "rst-selector-parser": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
+      "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=",
+      "dev": true,
+      "requires": {
+        "lodash.flattendeep": "^4.4.0",
+        "nearley": "^2.7.10"
+      }
+    },
     "rsvp": {
       "version": "4.8.4",
       "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.4.tgz",
@@ -10033,17 +10721,6 @@
           "requires": {
             "ms": "^2.1.1"
           }
-        },
-        "readable-stream": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz",
-          "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==",
-          "dev": true,
-          "requires": {
-            "inherits": "^2.0.3",
-            "string_decoder": "^1.1.1",
-            "util-deprecate": "^1.0.1"
-          }
         }
       }
     },
@@ -10101,9 +10778,9 @@
       "dev": true
     },
     "state-toggle": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz",
-      "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==",
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.2.tgz",
+      "integrity": "sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw==",
       "dev": true
     },
     "static-extend": {
@@ -10140,6 +10817,38 @@
       "dev": true,
       "requires": {
         "readable-stream": "^2.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "stealthy-require": {
@@ -10156,6 +10865,38 @@
       "requires": {
         "inherits": "~2.0.1",
         "readable-stream": "^2.0.2"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "stream-each": {
@@ -10179,6 +10920,38 @@
         "readable-stream": "^2.3.6",
         "to-arraybuffer": "^1.0.0",
         "xtend": "^4.0.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "stream-shift": {
@@ -10271,6 +11044,17 @@
         "function-bind": "^1.0.2"
       }
     },
+    "string.prototype.trim": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
+      "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.2",
+        "es-abstract": "^1.5.0",
+        "function-bind": "^1.0.2"
+      }
+    },
     "string.prototype.trimleft": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.0.0.tgz",
@@ -10290,9 +11074,9 @@
       }
     },
     "string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz",
+      "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==",
       "dev": true,
       "requires": {
         "safe-buffer": "~5.1.0"
@@ -10429,14 +11213,14 @@
           }
         },
         "cosmiconfig": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz",
-          "integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==",
+          "version": "5.2.1",
+          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+          "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
           "dev": true,
           "requires": {
             "import-fresh": "^2.0.0",
             "is-directory": "^0.3.1",
-            "js-yaml": "^3.13.0",
+            "js-yaml": "^3.13.1",
             "parse-json": "^4.0.0"
           }
         },
@@ -10626,9 +11410,9 @@
       }
     },
     "stylelint-scss": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.6.0.tgz",
-      "integrity": "sha512-Qpw0gl6iLBon5JNeFZjVYOEayd/e+WYIdY2vFhZuXeHC6jb8wl0wRZY97jATt/uxZzdtU3tGLAvJOUMuFp18vw==",
+      "version": "3.6.1",
+      "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.6.1.tgz",
+      "integrity": "sha512-6bB2EHUZsE/bDVKUdzBXqOcfgXmg3zq9Lglgbu16EqMa4PM8Y48XKcB8coOj8CKr07GtlqtOdCNA2E5njoI9Kw==",
       "dev": true,
       "requires": {
         "lodash": "^4.17.11",
@@ -10714,9 +11498,9 @@
       "dev": true
     },
     "table": {
-      "version": "5.2.3",
-      "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz",
-      "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==",
+      "version": "5.3.3",
+      "resolved": "https://registry.npmjs.org/table/-/table-5.3.3.tgz",
+      "integrity": "sha512-3wUNCgdWX6PNpOe3amTTPWPuF6VGvgzjKCaO1snFj0z7Y3mUPWf5+zDtxUVGispJkDECPmR29wbzh6bVMOHbcw==",
       "dev": true,
       "requires": {
         "ajv": "^6.9.1",
@@ -10745,13 +11529,13 @@
       "dev": true
     },
     "tar": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
-      "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
+      "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
       "dev": true,
       "requires": {
         "block-stream": "*",
-        "fstream": "^1.0.2",
+        "fstream": "^1.0.12",
         "inherits": "2"
       }
     },
@@ -10767,25 +11551,26 @@
       }
     },
     "terser-webpack-plugin": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz",
-      "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==",
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.4.tgz",
+      "integrity": "sha512-64IiILNQlACWZLzFlpzNaG0bpQ4ytaB7fwOsbpsdIV70AfLUmIGGeuKL0YV2WmtcrURjE2aOvHD4/lrFV3Rg+Q==",
       "dev": true,
       "requires": {
-        "cacache": "^11.0.2",
+        "cacache": "^11.3.2",
         "find-cache-dir": "^2.0.0",
+        "is-wsl": "^1.1.0",
         "schema-utils": "^1.0.0",
-        "serialize-javascript": "^1.4.0",
+        "serialize-javascript": "^1.7.0",
         "source-map": "^0.6.1",
-        "terser": "^3.16.1",
-        "webpack-sources": "^1.1.0",
-        "worker-farm": "^1.5.2"
+        "terser": "^3.17.0",
+        "webpack-sources": "^1.3.0",
+        "worker-farm": "^1.7.0"
       }
     },
     "test-exclude": {
-      "version": "5.2.2",
-      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.2.tgz",
-      "integrity": "sha512-N2pvaLpT8guUpb5Fe1GJlmvmzH3x+DAKmmyEQmFP792QcLYoGE1syxztSvPD1V8yPe6VrcCt6YGQVjSRjCASsA==",
+      "version": "5.2.3",
+      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
+      "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==",
       "dev": true,
       "requires": {
         "glob": "^7.1.3",
@@ -10808,6 +11593,38 @@
       "requires": {
         "readable-stream": "~2.3.6",
         "xtend": "~4.0.1"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
       }
     },
     "thunky": {
@@ -10944,15 +11761,15 @@
       "dev": true
     },
     "trim-trailing-lines": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz",
-      "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.2.tgz",
+      "integrity": "sha512-MUjYItdrqqj2zpcHFTkMa9WAv4JHTI6gnRQGPFLrt5L9a6tRMiDnIqYl8JBvu2d2Tc3lWJKQwlGCp0K8AvCM+Q==",
       "dev": true
     },
     "trough": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz",
-      "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.4.tgz",
+      "integrity": "sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==",
       "dev": true
     },
     "true-case-path": {
@@ -11014,9 +11831,9 @@
       }
     },
     "ts-loader": {
-      "version": "5.4.3",
-      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.3.tgz",
-      "integrity": "sha512-pHwZFkZioL7Yi2su0bhW2/djxZ+0iGat1cxlAif4Eg9j5znVYuWGtW0YYY/5w8W+IzLcAlD5KwJDrs5unUKIRA==",
+      "version": "5.4.5",
+      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz",
+      "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==",
       "dev": true,
       "requires": {
         "chalk": "^2.3.0",
@@ -11127,13 +11944,13 @@
       }
     },
     "type-is": {
-      "version": "1.6.16",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
-      "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+      "version": "1.6.18",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
       "dev": true,
       "requires": {
         "media-typer": "0.3.0",
-        "mime-types": "~2.1.18"
+        "mime-types": "~2.1.24"
       }
     },
     "typed-styles": {
@@ -11148,9 +11965,9 @@
       "dev": true
     },
     "typescript": {
-      "version": "3.4.4",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.4.tgz",
-      "integrity": "sha512-xt5RsIRCEaf6+j9AyOBgvVuAec0i92rgCaS3S+UVf5Z/vF2Hvtsw08wtUTJqp4djwznoAgjSxeCcU4r+CcDBJA==",
+      "version": "3.4.5",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz",
+      "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==",
       "dev": true
     },
     "ua-parser-js": {
@@ -11159,9 +11976,9 @@
       "integrity": "sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ=="
     },
     "uglify-js": {
-      "version": "3.5.6",
-      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.6.tgz",
-      "integrity": "sha512-YDKRX8F0Y+Jr7LhoVk0n4G7ltR3Y7qFAj+DtVBthlOgCcIj1hyMigCfousVfn9HKmvJ+qiFlLDwaHx44/e5ZKw==",
+      "version": "3.5.12",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.12.tgz",
+      "integrity": "sha512-KeQesOpPiZNgVwJj8Ge3P4JYbQHUdZzpx6Fahy6eKAYRSV4zhVmLXoC+JtOeYxcHCHTve8RG1ZGdTvpeOUM26Q==",
       "dev": true,
       "optional": true,
       "requires": {
@@ -11170,9 +11987,9 @@
       }
     },
     "unherit": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz",
-      "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz",
+      "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==",
       "dev": true,
       "requires": {
         "inherits": "^2.0.1",
@@ -11294,9 +12111,9 @@
       }
     },
     "unist-util-visit-parents": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz",
-      "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.0.tgz",
+      "integrity": "sha512-j0XZY3063E6v7qhx4+Q2Z0r8SMrLX7Mr6DabiCy67zMEcFQYtpNOplLlEK1KKEBEs9S+xB5U+yloQxbSwF9P/g==",
       "dev": true,
       "requires": {
         "unist-util-is": "^2.1.2"
@@ -11400,12 +12217,12 @@
       }
     },
     "url-parse": {
-      "version": "1.4.6",
-      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.6.tgz",
-      "integrity": "sha512-/B8AD9iQ01seoXmXf9z/MjLZQIdOoYl/+gvsQF6+mpnxaTfG9P7srYaiqaDMyKkR36XMXfhqSHss5MyFAO8lew==",
+      "version": "1.4.7",
+      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
+      "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
       "dev": true,
       "requires": {
-        "querystringify": "^2.0.0",
+        "querystringify": "^2.1.1",
         "requires-port": "^1.0.0"
       }
     },
@@ -11459,9 +12276,9 @@
       "dev": true
     },
     "v8-compile-cache": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz",
-      "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
+      "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==",
       "dev": true
     },
     "validate-npm-package-license": {
@@ -11549,6 +12366,12 @@
         "browser-process-hrtime": "^0.1.2"
       }
     },
+    "wait-for-expect": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/wait-for-expect/-/wait-for-expect-1.2.0.tgz",
+      "integrity": "sha512-EJhKpA+5UHixduMBEGhTFuLuVgQBKWxkFbefOdj2bbk2/OpA5Opsc4aUTGmF+qJ+v3kTGxDRNYwKaT4j6g5n8Q==",
+      "dev": true
+    },
     "walker": {
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
@@ -11593,9 +12416,9 @@
       "dev": true
     },
     "webpack": {
-      "version": "4.30.0",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.30.0.tgz",
-      "integrity": "sha512-4hgvO2YbAFUhyTdlR4FNyt2+YaYBYHavyzjCMbZzgglo02rlKi/pcsEzwCuCpsn1ryzIl1cq/u8ArIKu8JBYMg==",
+      "version": "4.31.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.31.0.tgz",
+      "integrity": "sha512-n6RVO3X0LbbipoE62akME9K/JI7qYrwwufs20VvgNNpqUoH4860KkaxJTbGq5bgkVZF9FqyyTG/0WPLH3PVNJA==",
       "dev": true,
       "requires": {
         "@webassemblyjs/ast": "1.8.5",
@@ -11671,9 +12494,9 @@
       }
     },
     "webpack-cli": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.1.tgz",
-      "integrity": "sha512-c2inFU7SM0IttEgF7fK6AaUsbBnORRzminvbyRKS+NlbQHVZdCtzKBlavRL5359bFsywXGRAItA5di/IruC8mg==",
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.2.tgz",
+      "integrity": "sha512-FLkobnaJJ+03j5eplxlI0TUxhGCOdfewspIGuvDVtpOlrAuKMFC57K42Ukxqs1tn8947/PM6tP95gQc0DCzRYA==",
       "dev": true,
       "requires": {
         "chalk": "^2.4.1",
@@ -11725,21 +12548,21 @@
       }
     },
     "webpack-dev-middleware": {
-      "version": "3.6.2",
-      "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.6.2.tgz",
-      "integrity": "sha512-A47I5SX60IkHrMmZUlB0ZKSWi29TZTcPz7cha1Z75yYOsgWh/1AcPmQEbC8ZIbU3A1ytSv1PMU0PyPz2Lmz2jg==",
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz",
+      "integrity": "sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==",
       "dev": true,
       "requires": {
         "memory-fs": "^0.4.1",
-        "mime": "^2.3.1",
-        "range-parser": "^1.0.3",
+        "mime": "^2.4.2",
+        "range-parser": "^1.2.1",
         "webpack-log": "^2.0.0"
       },
       "dependencies": {
         "mime": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz",
-          "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==",
+          "version": "2.4.3",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz",
+          "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==",
           "dev": true
         }
       }
@@ -11912,9 +12735,9 @@
       "dev": true
     },
     "worker-farm": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz",
-      "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==",
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+      "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
       "dev": true,
       "requires": {
         "errno": "~0.1.7"
diff --git a/web-console/package.json b/web-console/package.json
index 93beecb..ce7bea1 100644
--- a/web-console/package.json
+++ b/web-console/package.json
@@ -12,10 +12,16 @@
     "preset": "ts-jest",
     "testEnvironment": "jsdom",
     "moduleNameMapper": {
-      "\\.scss$": "identity-obj-proxy"
+      "\\.s?css$": "identity-obj-proxy"
     },
     "testMatch": [
       "**/?(*.)+(spec).ts?(x)"
+    ],
+    "snapshotSerializers": [
+      "enzyme-to-json/serializer"
+    ],
+    "setupFilesAfterEnv": [
+      "<rootDir>src/setup-tests.ts"
     ]
   },
   "scripts": {
@@ -24,6 +30,8 @@
     "pretest": "./script/build",
     "run": "./script/run",
     "test": "jest --silent 2>&1",
+    "coverage": "jest --coverage",
+    "update": "jest -u",
     "tslint": "./node_modules/.bin/tslint -c tslint.json --project tsconfig.json --formatters-dir ./node_modules/awesome-code-style/formatter 'src/**/*.ts?(x)'",
     "tslint-fix": "npm run tslint -- --fix",
     "tslint-changed-only": "git diff --diff-filter=ACMR --cached --name-only | grep -E \\.tsx\\?$ | xargs ./node_modules/.bin/tslint -c tslint.json --project tsconfig.json --formatters-dir ./node_modules/awesome-code-style/formatter",
@@ -58,12 +66,15 @@
   "devDependencies": {
     "@types/classnames": "^2.2.7",
     "@types/d3-array": "^2.0.0",
+    "@types/enzyme": "^3.9.1",
+    "@types/enzyme-adapter-react-16": "^1.0.5",
     "@types/file-saver": "^2.0.0",
     "@types/hjson": "^2.4.1",
     "@types/jest": "^24.0.11",
     "@types/lodash.debounce": "^4.0.6",
     "@types/node": "^11.13.4",
     "@types/numeral": "^0.0.25",
+    "@types/react": "^16.8.16",
     "@types/react-copy-to-clipboard": "^4.2.6",
     "@types/react-dom": "^16.8.4",
     "@types/react-router-dom": "^4.3.2",
@@ -71,15 +82,20 @@
     "autoprefixer": "^9.5.1",
     "awesome-code-style": "^1.2.2",
     "css-loader": "^2.1.1",
+    "enzyme": "^3.9.0",
+    "enzyme-adapter-react-16": "^1.12.1",
+    "enzyme-to-json": "^3.3.5",
+    "fs-extra": "^8.0.1",
     "identity-obj-proxy": "^3.0.0",
     "ignore-styles": "^5.0.1",
-    "jest": "^24.7.1",
+    "jest": "^24.8.0",
     "license-checker": "^25.0.1",
     "node-sass": "^4.11.0",
     "node-sass-chokidar": "^1.3.4",
     "postcss-cli": "^6.1.2",
     "postcss-loader": "^3.0.0",
     "postcss-preset-env": "^6.6.0",
+    "react-testing-library": "^7.0.0",
     "sass-loader": "^7.1.0",
     "style-loader": "^0.23.1",
     "stylelint": "^9.10.1",
diff --git a/web-console/src/bootstrap/react-table-defaults.tsx b/web-console/src/bootstrap/react-table-defaults.tsx
index 15ff727..b4dde83 100644
--- a/web-console/src/bootstrap/react-table-defaults.tsx
+++ b/web-console/src/bootstrap/react-table-defaults.tsx
@@ -19,7 +19,7 @@
 import * as React from 'react';
 import { Filter, ReactTableDefaults } from 'react-table';
 
-import { Loader } from '../components/loader';
+import { Loader } from '../components/loader/loader';
 import { booleanCustomTableFilter, countBy, makeTextFilter } from '../utils';
 
 import { ReactTableCustomPagination } from './react-table-custom-pagination';
diff --git a/web-console/src/components/action-cell/__snapshots__/action-cell.spec.tsx.snap b/web-console/src/components/action-cell/__snapshots__/action-cell.spec.tsx.snap
new file mode 100644
index 0000000..f3a8876
--- /dev/null
+++ b/web-console/src/components/action-cell/__snapshots__/action-cell.spec.tsx.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe action cell action cell snapshot 1`] = `
+<div
+  class="action-cell"
+>
+  <div>
+    hello world
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/action-cell.scss b/web-console/src/components/action-cell/action-cell.scss
similarity index 100%
rename from web-console/src/components/action-cell.scss
rename to web-console/src/components/action-cell/action-cell.scss
diff --git a/web-console/src/components/action-cell.tsx b/web-console/src/components/action-cell/action-cell.spec.tsx
similarity index 68%
copy from web-console/src/components/action-cell.tsx
copy to web-console/src/components/action-cell/action-cell.spec.tsx
index e37b2c9..4683591 100644
--- a/web-console/src/components/action-cell.tsx
+++ b/web-console/src/components/action-cell/action-cell.spec.tsx
@@ -16,21 +16,20 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
 
-import './action-cell.scss';
 
-export interface ActionCellProps extends React.Props<any> {
-}
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export class ActionCell extends React.Component<ActionCellProps, {}> {
-  constructor(props: ActionCellProps, context: any) {
-    super(props, context);
-  }
+import { ActionCell} from './action-cell';
 
-  render() {
-    return <div className="action-cell">
-      {this.props.children}
-    </div>;
-  }
-}
+describe('describe action cell', () => {
+  it('action cell snapshot', () => {
+    const actionCell =
+      <ActionCell >
+        <div>hello world</div>
+      </ActionCell>;
+    const { container, getByText } = render(actionCell);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/action-cell.tsx b/web-console/src/components/action-cell/action-cell.tsx
similarity index 100%
copy from web-console/src/components/action-cell.tsx
copy to web-console/src/components/action-cell/action-cell.tsx
diff --git a/web-console/src/components/array-input/__snapshots__/array-input.spec.tsx.snap b/web-console/src/components/array-input/__snapshots__/array-input.spec.tsx.snap
new file mode 100644
index 0000000..89823bc
--- /dev/null
+++ b/web-console/src/components/array-input/__snapshots__/array-input.spec.tsx.snap
@@ -0,0 +1,10 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe array input array input snapshot 1`] = `
+<textarea
+  class="bp3-input bp3-fill test"
+  placeholder="test"
+>
+  apple, banana, pear
+</textarea>
+`;
diff --git a/web-console/src/components/view-control-bar.tsx b/web-console/src/components/array-input/array-input.spec.tsx
similarity index 61%
copy from web-console/src/components/view-control-bar.tsx
copy to web-console/src/components/array-input/array-input.spec.tsx
index 679c671..3b858e4 100644
--- a/web-console/src/components/view-control-bar.tsx
+++ b/web-console/src/components/array-input/array-input.spec.tsx
@@ -16,25 +16,24 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
-
-import './view-control-bar.scss';
 
-export interface ViewControlBarProps {
-  label: string;
-}
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export class ViewControlBar extends React.Component<ViewControlBarProps, {}> {
-  constructor(props: ViewControlBarProps) {
-    super(props);
-  }
+import {MenuCheckbox} from '../menu-checkbox/menu-checkbox';
 
-  render() {
-    const { label, children } = this.props;
+import {ArrayInput} from './array-input';
 
-    return <div className="view-control-bar">
-      <div className="control-label">{label}</div>
-      {children}
-    </div>;
-  }
-}
+describe('describe array input', () => {
+  it('array input snapshot', () => {
+    const arrayInput =
+      <ArrayInput
+        values={['apple', 'banana', 'pear']}
+        className={'test'}
+        placeholder={'test'}
+        onChange={() => null}
+      />;
+    const { container, getByText } = render(arrayInput);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/array-input.tsx b/web-console/src/components/array-input/array-input.tsx
similarity index 91%
rename from web-console/src/components/array-input.tsx
rename to web-console/src/components/array-input/array-input.tsx
index e771d44..6af8cbf 100644
--- a/web-console/src/components/array-input.tsx
+++ b/web-console/src/components/array-input/array-input.tsx
@@ -20,8 +20,13 @@
 import { ITagInputProps, TextArea } from '@blueprintjs/core';
 import * as React from 'react';
 
-export interface ArrayInputProps extends ITagInputProps {
-
+export interface ArrayInputProps {
+  className?: string;
+  values: string[];
+  onChange: (newValues: string[]) => void;
+  placeholder?: string;
+  large?: boolean;
+  disabled?: boolean;
 }
 
 export class ArrayInput extends React.Component<ArrayInputProps, { stringValue: string }> {
diff --git a/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap b/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap
new file mode 100644
index 0000000..7e581ec
--- /dev/null
+++ b/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap
@@ -0,0 +1,489 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe auto-form snapshot auto-form snapshot 1`] = `
+<div
+  class="auto-form"
+>
+  <div
+    class="bp3-form-group"
+  >
+    <label
+      class="bp3-label"
+    >
+      Test one
+       
+      <span
+        class="bp3-text-muted"
+      />
+    </label>
+    <div
+      class="bp3-form-content"
+    >
+      <div
+        class="bp3-control-group bp3-fill bp3-numeric-input"
+      >
+        <div
+          class="bp3-input-group"
+        >
+          <input
+            autocomplete="off"
+            class="bp3-input"
+            min="0"
+            style="padding-right: 10px;"
+            type="text"
+            value=""
+          />
+        </div>
+        <div
+          class="bp3-button-group bp3-vertical bp3-fixed"
+        >
+          <button
+            class="bp3-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-chevron-up"
+              icon="chevron-up"
+            >
+              <svg
+                data-icon="chevron-up"
+                height="16"
+                viewBox="0 0 16 16"
+                width="16"
+              >
+                <desc>
+                  chevron-up
+                </desc>
+                <path
+                  d="M12.71 9.29l-4-4C8.53 5.11 8.28 5 8 5s-.53.11-.71.29l-4 4a1.003 1.003 0 0 0 1.42 1.42L8 7.41l3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+          <button
+            class="bp3-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-chevron-down"
+              icon="chevron-down"
+            >
+              <svg
+                data-icon="chevron-down"
+                height="16"
+                viewBox="0 0 16 16"
+                width="16"
+              >
+                <desc>
+                  chevron-down
+                </desc>
+                <path
+                  d="M12 5c-.28 0-.53.11-.71.29L8 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42l4 4c.18.18.43.29.71.29s.53-.11.71-.29l4-4A1.003 1.003 0 0 0 12 5z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div
+    class="bp3-form-group"
+  >
+    <label
+      class="bp3-label"
+    >
+      Test two
+       
+      <span
+        class="bp3-text-muted"
+      />
+    </label>
+    <div
+      class="bp3-form-content"
+    >
+      <div
+        class="bp3-control-group bp3-numeric-input"
+      >
+        <div
+          class="bp3-input-group"
+        >
+          <input
+            autocomplete="off"
+            class="bp3-input"
+            min="0"
+            style="padding-right: 10px;"
+            type="text"
+            value=""
+          />
+        </div>
+        <div
+          class="bp3-button-group bp3-vertical bp3-fixed"
+        >
+          <button
+            class="bp3-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-chevron-up"
+              icon="chevron-up"
+            >
+              <svg
+                data-icon="chevron-up"
+                height="16"
+                viewBox="0 0 16 16"
+                width="16"
+              >
+                <desc>
+                  chevron-up
+                </desc>
+                <path
+                  d="M12.71 9.29l-4-4C8.53 5.11 8.28 5 8 5s-.53.11-.71.29l-4 4a1.003 1.003 0 0 0 1.42 1.42L8 7.41l3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+          <button
+            class="bp3-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-chevron-down"
+              icon="chevron-down"
+            >
+              <svg
+                data-icon="chevron-down"
+                height="16"
+                viewBox="0 0 16 16"
+                width="16"
+              >
+                <desc>
+                  chevron-down
+                </desc>
+                <path
+                  d="M12 5c-.28 0-.53.11-.71.29L8 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42l4 4c.18.18.43.29.71.29s.53-.11.71-.29l4-4A1.003 1.003 0 0 0 12 5z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div
+    class="bp3-form-group"
+  >
+    <label
+      class="bp3-label"
+    >
+      Test three
+       
+      <span
+        class="bp3-text-muted"
+      />
+    </label>
+    <div
+      class="bp3-form-content"
+    >
+      <div
+        class="bp3-input-group"
+      >
+        <input
+          class="bp3-input"
+          style="padding-right: 10px;"
+          type="text"
+          value=""
+        />
+      </div>
+    </div>
+  </div>
+  <div
+    class="bp3-form-group"
+  >
+    <label
+      class="bp3-label"
+    >
+      Test four
+       
+      <span
+        class="bp3-text-muted"
+      />
+    </label>
+    <div
+      class="bp3-form-content"
+    >
+      <div
+        class="bp3-html-select"
+      >
+        <select>
+          <option
+            value="True"
+          >
+            True
+          </option>
+          <option
+            value="False"
+          >
+            False
+          </option>
+        </select>
+        <span
+          class="bp3-icon bp3-icon-double-caret-vertical"
+          icon="double-caret-vertical"
+        >
+          <svg
+            data-icon="double-caret-vertical"
+            height="16"
+            viewBox="0 0 16 16"
+            width="16"
+          >
+            <desc>
+              double-caret-vertical
+            </desc>
+            <path
+              d="M5 7h6a1.003 1.003 0 0 0 .71-1.71l-3-3C8.53 2.11 8.28 2 8 2s-.53.11-.71.29l-3 3A1.003 1.003 0 0 0 5 7zm6 2H5a1.003 1.003 0 0 0-.71 1.71l3 3c.18.18.43.29.71.29s.53-.11.71-.29l3-3A1.003 1.003 0 0 0 11 9z"
+              fill-rule="evenodd"
+            />
+          </svg>
+        </span>
+      </div>
+    </div>
+  </div>
+  <div
+    class="bp3-form-group"
+  >
+    <label
+      class="bp3-label"
+    >
+      Test five
+       
+      <span
+        class="bp3-text-muted"
+      />
+    </label>
+    <div
+      class="bp3-form-content"
+    >
+      <textarea
+        class="bp3-input bp3-fill"
+      />
+    </div>
+  </div>
+  <div
+    class="bp3-form-group"
+  >
+    <label
+      class="bp3-label"
+    >
+      Test six
+       
+      <span
+        class="bp3-text-muted"
+      />
+    </label>
+    <div
+      class="bp3-form-content"
+    >
+      <div
+        class=" ace_editor ace-tm"
+        id="ace-editor"
+        style="width: 100%; height: 8vh;"
+      >
+        <textarea
+          autocapitalize="off"
+          autocorrect="off"
+          class="ace_text-input"
+          spellcheck="false"
+          style="opacity: 0;"
+          wrap="off"
+        />
+        <div
+          aria-hidden="true"
+          class="ace_gutter"
+          style="display: none;"
+        >
+          <div
+            class="ace_layer ace_gutter-layer ace_folding-enabled"
+          />
+          <div
+            class="ace_gutter-active-line"
+          />
+        </div>
+        <div
+          class="ace_scroller"
+        >
+          <div
+            class="ace_content"
+          >
+            <div
+              class="ace_layer ace_print-margin-layer"
+            >
+              <div
+                class="ace_print-margin"
+                style="left: 4px; visibility: hidden;"
+              />
+            </div>
+            <div
+              class="ace_layer ace_marker-layer"
+            />
+            <div
+              class="ace_layer ace_text-layer"
+              style="padding: 0px 4px;"
+            />
+            <div
+              class="ace_layer ace_marker-layer"
+            />
+            <div
+              class="ace_layer ace_cursor-layer ace_hidden-cursors"
+            >
+              <div
+                class="ace_cursor"
+              />
+            </div>
+          </div>
+        </div>
+        <div
+          class="ace_scrollbar ace_scrollbar-v"
+          style="display: none; width: 20px;"
+        >
+          <div
+            class="ace_scrollbar-inner"
+            style="width: 20px;"
+          />
+        </div>
+        <div
+          class="ace_scrollbar ace_scrollbar-h"
+          style="display: none; height: 20px;"
+        >
+          <div
+            class="ace_scrollbar-inner"
+            style="height: 20px;"
+          />
+        </div>
+        <div
+          style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
+        >
+          <div
+            style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+          />
+          <div
+            style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+          >
+            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div
+    class="bp3-form-group"
+  >
+    <label
+      class="bp3-label"
+    >
+      Test seven
+       
+      <span
+        class="bp3-text-muted"
+      />
+    </label>
+    <div
+      class="bp3-form-content"
+    >
+      <div
+        class=" ace_editor ace-tm"
+        id="ace-editor"
+        style="width: 100%; height: 8vh;"
+      >
+        <textarea
+          autocapitalize="off"
+          autocorrect="off"
+          class="ace_text-input"
+          spellcheck="false"
+          style="opacity: 0;"
+          wrap="off"
+        />
+        <div
+          aria-hidden="true"
+          class="ace_gutter"
+          style="display: none;"
+        >
+          <div
+            class="ace_layer ace_gutter-layer ace_folding-enabled"
+          />
+          <div
+            class="ace_gutter-active-line"
+          />
+        </div>
+        <div
+          class="ace_scroller"
+        >
+          <div
+            class="ace_content"
+          >
+            <div
+              class="ace_layer ace_print-margin-layer"
+            >
+              <div
+                class="ace_print-margin"
+                style="left: 4px; visibility: hidden;"
+              />
+            </div>
+            <div
+              class="ace_layer ace_marker-layer"
+            />
+            <div
+              class="ace_layer ace_text-layer"
+              style="padding: 0px 4px;"
+            />
+            <div
+              class="ace_layer ace_marker-layer"
+            />
+            <div
+              class="ace_layer ace_cursor-layer ace_hidden-cursors"
+            >
+              <div
+                class="ace_cursor"
+              />
+            </div>
+          </div>
+        </div>
+        <div
+          class="ace_scrollbar ace_scrollbar-v"
+          style="display: none; width: 20px;"
+        >
+          <div
+            class="ace_scrollbar-inner"
+            style="width: 20px;"
+          />
+        </div>
+        <div
+          class="ace_scrollbar ace_scrollbar-h"
+          style="display: none; height: 20px;"
+        >
+          <div
+            class="ace_scrollbar-inner"
+            style="height: 20px;"
+          />
+        </div>
+        <div
+          style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
+        >
+          <div
+            style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+          />
+          <div
+            style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+          >
+            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/auto-form.scss b/web-console/src/components/auto-form/auto-form.scss
similarity index 100%
copy from web-console/src/components/auto-form.scss
copy to web-console/src/components/auto-form/auto-form.scss
diff --git a/web-console/src/components/menu-checkbox.tsx b/web-console/src/components/auto-form/auto-form.spec.tsx
similarity index 52%
copy from web-console/src/components/menu-checkbox.tsx
copy to web-console/src/components/auto-form/auto-form.spec.tsx
index 21b438b..2912924 100644
--- a/web-console/src/components/menu-checkbox.tsx
+++ b/web-console/src/components/auto-form/auto-form.spec.tsx
@@ -16,16 +16,27 @@
  * limitations under the License.
  */
 
-import { Checkbox, ICheckboxProps } from '@blueprintjs/core';
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-import './menu-checkbox.scss';
+import {AutoForm} from './auto-form';
 
-export class MenuCheckbox extends React.Component<ICheckboxProps, {}> {
 
-  render() {
-    return <li className="menu-checkbox">
-      <Checkbox {...this.props}/>
-    </li>;
-  }
-}
+describe('describe auto-form snapshot', () => {
+  it('auto-form snapshot', () => {
+    const autoForm =
+      <AutoForm
+        fields={[{name: 'testOne', type: 'number'},
+          {name: 'testTwo', type: 'size-bytes'},
+          {name: 'testThree', type: 'string'},
+          {name: 'testFour', type: 'boolean'},
+          {name: 'testFive', type: 'string-array'},
+          {name: 'testSix', type: 'json'},
+          {name: 'testSeven', type: 'json'}]}
+        model={String}
+        onChange={(newModel: Record<string, any>) => {}}
+      />;
+    const { container, getByText } = render(autoForm);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/auto-form.tsx b/web-console/src/components/auto-form/auto-form.tsx
similarity index 95%
rename from web-console/src/components/auto-form.tsx
rename to web-console/src/components/auto-form/auto-form.tsx
index 9787699..6a54af7 100644
--- a/web-console/src/components/auto-form.tsx
+++ b/web-console/src/components/auto-form/auto-form.tsx
@@ -31,10 +31,9 @@ import {
 import { IconNames } from '@blueprintjs/icons';
 import * as React from 'react';
 
-import { deepDelete, deepGet, deepSet } from '../utils/object-change';
-
-import { ArrayInput } from './array-input';
-import { JSONInput } from './json-input';
+import { deepDelete, deepGet, deepSet } from '../../utils/object-change';
+import { ArrayInput } from '../array-input/array-input';
+import { JSONInput } from '../json-input/json-input';
 
 import './auto-form.scss';
 
@@ -184,7 +183,7 @@ export class AutoForm<T extends Record<string, any>> extends React.Component<Aut
       rightElement={
         suggestionsMenu &&
         <Popover content={suggestionsMenu} position={Position.BOTTOM_RIGHT} autoFocus={false}>
-          <Button icon={IconNames.CARET_DOWN} minimal />
+            <Button icon={IconNames.CARET_DOWN} minimal />
         </Popover>
       }
       large={large}
@@ -240,8 +239,6 @@ export class AutoForm<T extends Record<string, any>> extends React.Component<Aut
         this.fieldChange(field, v);
       }}
       placeholder={field.placeholder}
-      addOnBlur
-      fill
       large={large}
       disabled={field.disabled}
     />;
@@ -272,10 +269,10 @@ export class AutoForm<T extends Record<string, any>> extends React.Component<Aut
       labelInfo={
         field.info &&
         <Popover
-          content={<div className="label-info-text">{field.info}</div>}
-          position="left-bottom"
+            content={<div className="label-info-text">{field.info}</div>}
+            position="left-bottom"
         >
-          <Icon icon={IconNames.INFO_SIGN} iconSize={14}/>
+            <Icon icon={IconNames.INFO_SIGN} iconSize={14}/>
         </Popover>
       }
     >
diff --git a/web-console/src/components/center-message/__snapshots__/center-message.spec.tsx.snap b/web-console/src/components/center-message/__snapshots__/center-message.spec.tsx.snap
new file mode 100644
index 0000000..2e9140d
--- /dev/null
+++ b/web-console/src/components/center-message/__snapshots__/center-message.spec.tsx.snap
@@ -0,0 +1,15 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`decribe center-message center-message snapshot 1`] = `
+<div
+  class="center-message bp3-input"
+>
+  <div
+    class="center-message-inner"
+  >
+    <div>
+      Hello World
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/center-message.scss b/web-console/src/components/center-message/center-message.scss
similarity index 100%
rename from web-console/src/components/center-message.scss
rename to web-console/src/components/center-message/center-message.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/center-message/center-message.spec.tsx
similarity index 67%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/center-message/center-message.spec.tsx
index 0a9c102..6787c0a 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/center-message/center-message.spec.tsx
@@ -17,20 +17,18 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import { CenterMessage } from './center-message';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
+describe('decribe center-message', () => {
+  it('center-message snapshot', () => {
+    const centerMessage =
+      <CenterMessage>
+        <div>Hello World</div>
+      </CenterMessage>;
 
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+    const { container, getByText } = render(centerMessage);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/center-message.tsx b/web-console/src/components/center-message/center-message.tsx
similarity index 100%
rename from web-console/src/components/center-message.tsx
rename to web-console/src/components/center-message/center-message.tsx
diff --git a/web-console/src/components/clearable-input/__snapshots__/clearable-input.spec.tsx.snap b/web-console/src/components/clearable-input/__snapshots__/clearable-input.spec.tsx.snap
new file mode 100644
index 0000000..c6ef24b
--- /dev/null
+++ b/web-console/src/components/clearable-input/__snapshots__/clearable-input.spec.tsx.snap
@@ -0,0 +1,43 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`decribe clearable-input clearable-input snapshot 1`] = `
+<div
+  class="bp3-input-group clearable-input testClassName"
+>
+  <input
+    class="bp3-input"
+    placeholder="testPlaceholder"
+    style="padding-right: 0px;"
+    type="text"
+    value="testValue"
+  />
+  <span
+    class="bp3-input-action"
+  >
+    <button
+      class="bp3-button bp3-minimal"
+      type="button"
+    >
+      <span
+        class="bp3-icon bp3-icon-cross"
+        icon="cross"
+      >
+        <svg
+          data-icon="cross"
+          height="16"
+          viewBox="0 0 16 16"
+          width="16"
+        >
+          <desc>
+            cross
+          </desc>
+          <path
+            d="M9.41 8l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L8 6.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42L6.59 8 3.3 11.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71L8 9.41l3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L9.41 8z"
+            fill-rule="evenodd"
+          />
+        </svg>
+      </span>
+    </button>
+  </span>
+</div>
+`;
diff --git a/web-console/src/components/view-control-bar.tsx b/web-console/src/components/clearable-input/clearable-input.spec.tsx
similarity index 59%
copy from web-console/src/components/view-control-bar.tsx
copy to web-console/src/components/clearable-input/clearable-input.spec.tsx
index 679c671..1ce62cc 100644
--- a/web-console/src/components/view-control-bar.tsx
+++ b/web-console/src/components/clearable-input/clearable-input.spec.tsx
@@ -17,24 +17,24 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-import './view-control-bar.scss';
+import {ClearableInput} from './clearable-input';
 
-export interface ViewControlBarProps {
-  label: string;
-}
 
-export class ViewControlBar extends React.Component<ViewControlBarProps, {}> {
-  constructor(props: ViewControlBarProps) {
-    super(props);
-  }
+describe('decribe clearable-input', () => {
+  it('clearable-input snapshot', () => {
+    const centerMessage =
+      <ClearableInput
+        className={'testClassName'}
+        value={'testValue'}
+        placeholder={'testPlaceholder'}
+        onChange={(value: string) => null}
+      >;
+        <div>Hello World</div>
+      </ClearableInput>;
 
-  render() {
-    const { label, children } = this.props;
-
-    return <div className="view-control-bar">
-      <div className="control-label">{label}</div>
-      {children}
-    </div>;
-  }
-}
+    const { container, getByText } = render(centerMessage);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/clearable-input.tsx b/web-console/src/components/clearable-input/clearable-input.tsx
similarity index 100%
copy from web-console/src/components/clearable-input.tsx
copy to web-console/src/components/clearable-input/clearable-input.tsx
diff --git a/web-console/src/components/external-link/__snapshots__/external-link.spec.tsx.snap b/web-console/src/components/external-link/__snapshots__/external-link.spec.tsx.snap
new file mode 100644
index 0000000..3b8a139
--- /dev/null
+++ b/web-console/src/components/external-link/__snapshots__/external-link.spec.tsx.snap
@@ -0,0 +1,12 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe external link external link snapshot 1`] = `
+<a
+  href="http://test/"
+  target="_blank"
+>
+  <div>
+    hello world
+  </div>
+</a>
+`;
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/external-link/external-link.spec.tsx
similarity index 66%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/external-link/external-link.spec.tsx
index 0a9c102..a4835ac 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/external-link/external-link.spec.tsx
@@ -17,20 +17,18 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {ExternalLink} from './external-link';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
+describe('describe external link', () => {
+  it('external link snapshot', () => {
+    const externalLink =
+      <ExternalLink href={'http://test/'}>
+        <div>hello world</div>
+      </ExternalLink>;
 
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+    const { container, getByText } = render(externalLink);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/external-link/external-link.tsx
similarity index 100%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/external-link/external-link.tsx
diff --git a/web-console/src/components/header-bar/__snapshots__/header-bar.spec.tsx.snap b/web-console/src/components/header-bar/__snapshots__/header-bar.spec.tsx.snap
new file mode 100644
index 0000000..29b24e3
--- /dev/null
+++ b/web-console/src/components/header-bar/__snapshots__/header-bar.spec.tsx.snap
@@ -0,0 +1,290 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe header bar header bar snapshot 1`] = `
+<Blueprint3.Navbar
+  className="header-bar"
+>
+  <Blueprint3.NavbarGroup
+    align="left"
+  >
+    <a
+      href="#"
+    >
+      <div
+        className="logo"
+      >
+        <svg
+          version="1.1"
+          viewBox="0 0 288 134"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            d="M136.7,67.5c0.5-6.1,5-10.4,10.6-10.4c3.9,0,6.5,2,7.4,4.3l1.1-12.4c0-0.1,0.3-0.2,0.7-0.2
+                c0.7,0,1.3,0.4,1.2,2l-2.3,25.9c-0.1,0.7-0.5,1-1,1h-0.2c-0.6,0-0.9-0.3-0.8-1l0.3-3.2c-1.7,2.7-4.5,4.5-8.3,4.5
+                C139.9,77.9,136.2,73.7,136.7,67.5z M154,68.9l0.4-4.7c-0.9-3.3-3.3-5.4-7.2-5.4c-4.5,0-8.1,3.6-8.5,8.6
+                c-0.4,5.1,2.5,8.7,6.9,8.7C150,76.1,153.7,72.9,154,68.9z"
+            fill="#FFFFFF"
+          />
+          <path
+            d="M161.2,76.6l1.7-19.1c0,0,0.3-0.2,0.7-0.2c0.7,0,1.3,0.4,1.1,2l-0.2,2.5c1.1-3.3,3.3-4.8,6-4.8
+                c1.6,0,2.7,0.7,2.6,1.7c-0.1,0.8-0.6,1.1-0.7,1.1c-0.5-0.5-1.3-0.8-2.3-0.8c-3.6,0-5.6,3.6-6.1,9l-0.8,8.7c-0.1,0.7-0.5,1-1,1
+                h-0.2C161.5,77.6,161.2,77.4,161.2,76.6z"
+            fill="#FFFFFF"
+          />
+          <path
+            d="M175.6,69l0.9-10.7c0.1-0.8,0.5-1,1-1h0.3c0.5,0,0.9,0.2,0.8,1l-0.9,10.5c-0.4,4.4,1.5,7.2,5.5,7.2
+                c3.3,0,6-1.9,7.5-4.7l1.1-13c0.1-0.8,0.5-1,1-1h0.3c0.5,0,0.9,0.2,0.8,1l-1.7,19.1c0,0-0.4,0.2-0.7,0.2c-0.7,0-1.2-0.4-1.1-2
+                l0.2-1.8c-1.6,2.4-4.2,4.1-7.6,4.1C177.6,77.9,175.2,74.4,175.6,69z"
+            fill="#FFFFFF"
+          />
+          <path
+            d="M200.1,50.7c0.1-1,0.6-1.4,1.6-1.4c0.9,0,1.4,0.5,1.3,1.4c-0.1,0.9-0.6,1.4-1.6,1.4
+                C200.5,52.1,200,51.6,200.1,50.7z M198.2,76.6l1.6-18.3c0.1-0.8,0.5-1,1-1h0.3c0.5,0,0.9,0.2,0.8,1l-1.6,18.3
+                c-0.1,0.8-0.5,1-1,1H199C198.5,77.6,198.2,77.4,198.2,76.6z"
+            fill="#FFFFFF"
+          />
+          <path
+            d="M205.8,67.5c0.5-6.1,5-10.4,10.6-10.4c3.9,0,6.5,2,7.4,4.3l1.1-12.4c0-0.1,0.3-0.2,0.7-0.2
+                c0.7,0,1.3,0.4,1.2,2l-2.3,25.9c-0.1,0.7-0.5,1-1,1h-0.2c-0.5,0-0.9-0.3-0.8-1l0.3-3.2c-1.7,2.7-4.5,4.5-8.3,4.5
+                C209,77.9,205.2,73.7,205.8,67.5z M223.1,68.9l0.4-4.7c-0.9-3.3-3.3-5.4-7.2-5.4c-4.5,0-8.1,3.6-8.5,8.6
+                c-0.4,5.1,2.5,8.7,6.9,8.7C219,76.1,222.7,72.9,223.1,68.9z"
+            fill="#FFFFFF"
+          />
+          <path
+            d="M96.2,89.8h-2.7c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h2.7c11.5,0,23.8-7.4,23.8-23.7
+                c0-9.1-6.9-15.8-16.4-15.8H80c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h23.6c5.3,0,10.1,1.9,13.6,5.3
+                c3.5,3.4,5.4,8,5.4,13.1c0,6.6-2.3,13-6.3,17.7C111.5,86.8,104.5,89.8,96.2,89.8z M87.1,89.8h-5.8c-0.7,0-1.3-0.6-1.3-1.3
+                c0-0.7,0.6-1.3,1.3-1.3h5.8c0.7,0,1.3,0.6,1.3,1.3C88.4,89.2,87.8,89.8,87.1,89.8z M97.7,79.5h-26c-0.7,0-1.3-0.6-1.3-1.3
+                c0-0.7,0.6-1.3,1.3-1.3h26c7.5,0,11.5-5.8,11.5-11.5c0-4.2-3.2-7.3-7.7-7.3h-26c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3
+                h26c5.9,0,10.3,4.3,10.3,9.9c0,3.7-1.3,7.2-3.7,9.8C105.5,78,101.9,79.5,97.7,79.5z M69.2,58h-6.3c-0.7,0-1.3-0.6-1.3-1.3
+                c0-0.7,0.6-1.3,1.3-1.3h6.3c0.7,0,1.3,0.6,1.3,1.3C70.5,57.4,69.9,58,69.2,58z"
+            fill="#2CEEFB"
+          />
+        </svg>
+      </div>
+    </a>
+    <Blueprint3.NavbarDivider />
+    <Blueprint3.AnchorButton
+      active={true}
+      href="#load-data"
+      icon="cloud-upload"
+      intent="none"
+      minimal={true}
+      text="Load data"
+    />
+    <Blueprint3.NavbarDivider />
+    <Blueprint3.AnchorButton
+      active={false}
+      href="#datasources"
+      icon="multi-select"
+      minimal={true}
+      text="Datasources"
+    />
+    <Blueprint3.AnchorButton
+      active={false}
+      href="#segments"
+      icon="stacked-chart"
+      minimal={true}
+      text="Segments"
+    />
+    <Blueprint3.AnchorButton
+      active={false}
+      href="#tasks"
+      icon="gantt-chart"
+      minimal={true}
+      text="Tasks"
+    />
+    <Blueprint3.AnchorButton
+      active={false}
+      href="#servers"
+      icon="database"
+      minimal={true}
+      text="Data servers"
+    />
+    <Blueprint3.NavbarDivider />
+    <Blueprint3.AnchorButton
+      active={false}
+      href="#query"
+      icon="application"
+      minimal={true}
+      text="Query"
+    />
+  </Blueprint3.NavbarGroup>
+  <Blueprint3.NavbarGroup
+    align="right"
+  >
+    <Blueprint3.Popover
+      boundary="scrollParent"
+      captureDismiss={false}
+      content={
+        <Blueprint3.Menu>
+          <Blueprint3.MenuItem
+            disabled={false}
+            href="/index.html"
+            icon="graph"
+            multiline={false}
+            popoverProps={Object {}}
+            shouldDismissPopover={true}
+            target="_blank"
+            text="Legacy coordinator console"
+          />
+          <Blueprint3.MenuItem
+            disabled={false}
+            href="/console.html"
+            icon="map"
+            multiline={false}
+            popoverProps={Object {}}
+            shouldDismissPopover={true}
+            target="_blank"
+            text="Legacy overlord console"
+          />
+        </Blueprint3.Menu>
+      }
+      defaultIsOpen={false}
+      disabled={false}
+      hasBackdrop={false}
+      hoverCloseDelay={300}
+      hoverOpenDelay={150}
+      inheritDarkTheme={true}
+      interactionKind="click"
+      minimal={false}
+      modifiers={Object {}}
+      openOnTargetFocus={true}
+      position="bottom-right"
+      targetTagName="span"
+      transitionDuration={300}
+      usePortal={true}
+      wrapperTagName="span"
+    >
+      <Blueprint3.Button
+        icon="share"
+        minimal={true}
+        text="Legacy"
+      />
+    </Blueprint3.Popover>
+    <Blueprint3.Popover
+      boundary="scrollParent"
+      captureDismiss={false}
+      content={
+        <Blueprint3.Menu>
+          <Blueprint3.MenuItem
+            disabled={false}
+            icon="settings"
+            multiline={false}
+            onClick={[Function]}
+            popoverProps={Object {}}
+            shouldDismissPopover={true}
+            text="Coordinator dynamic config"
+          />
+          <Blueprint3.MenuItem
+            disabled={false}
+            icon="wrench"
+            multiline={false}
+            onClick={[Function]}
+            popoverProps={Object {}}
+            shouldDismissPopover={true}
+            text="Overlord dynamic config"
+          />
+          <Blueprint3.MenuItem
+            active={false}
+            disabled={false}
+            href="#lookups"
+            icon="properties"
+            multiline={false}
+            popoverProps={Object {}}
+            shouldDismissPopover={true}
+            text="Lookups"
+          />
+        </Blueprint3.Menu>
+      }
+      defaultIsOpen={false}
+      disabled={false}
+      hasBackdrop={false}
+      hoverCloseDelay={300}
+      hoverOpenDelay={150}
+      inheritDarkTheme={true}
+      interactionKind="click"
+      minimal={false}
+      modifiers={Object {}}
+      openOnTargetFocus={true}
+      position="bottom-right"
+      targetTagName="span"
+      transitionDuration={300}
+      usePortal={true}
+      wrapperTagName="span"
+    >
+      <Blueprint3.Button
+        icon="cog"
+        minimal={true}
+      />
+    </Blueprint3.Popover>
+    <Blueprint3.Popover
+      boundary="scrollParent"
+      captureDismiss={false}
+      content={
+        <Blueprint3.Menu>
+          <Blueprint3.MenuItem
+            disabled={false}
+            icon="graph"
+            multiline={false}
+            onClick={[Function]}
+            popoverProps={Object {}}
+            shouldDismissPopover={true}
+            text="About"
+          />
+          <Blueprint3.MenuItem
+            disabled={false}
+            href="http://druid.io/docs/latest"
+            icon="th"
+            multiline={false}
+            popoverProps={Object {}}
+            shouldDismissPopover={true}
+            target="_blank"
+            text="Docs"
+          />
+          <Blueprint3.MenuItem
+            disabled={false}
+            href="https://groups.google.com/forum/#!forum/druid-user"
+            icon="user"
+            multiline={false}
+            popoverProps={Object {}}
+            shouldDismissPopover={true}
+            target="_blank"
+            text="User group"
+          />
+          <Blueprint3.MenuItem
+            disabled={false}
+            href="https://github.com/apache/druid"
+            icon="git-branch"
+            multiline={false}
+            popoverProps={Object {}}
+            shouldDismissPopover={true}
+            target="_blank"
+            text="GitHub"
+          />
+        </Blueprint3.Menu>
+      }
+      defaultIsOpen={false}
+      disabled={false}
+      hasBackdrop={false}
+      hoverCloseDelay={300}
+      hoverOpenDelay={150}
+      inheritDarkTheme={true}
+      interactionKind="click"
+      minimal={false}
+      modifiers={Object {}}
+      openOnTargetFocus={true}
+      position="bottom-right"
+      targetTagName="span"
+      transitionDuration={300}
+      usePortal={true}
+      wrapperTagName="span"
+    >
+      <Blueprint3.Button
+        icon="help"
+        minimal={true}
+      />
+    </Blueprint3.Popover>
+  </Blueprint3.NavbarGroup>
+</Blueprint3.Navbar>
+`;
diff --git a/web-console/src/components/header-bar.scss b/web-console/src/components/header-bar/header-bar.scss
similarity index 100%
rename from web-console/src/components/header-bar.scss
rename to web-console/src/components/header-bar/header-bar.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/header-bar/header-bar.spec.tsx
similarity index 70%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/header-bar/header-bar.spec.tsx
index 0a9c102..7299103 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/header-bar/header-bar.spec.tsx
@@ -16,21 +16,20 @@
  * limitations under the License.
  */
 
+import { shallow } from 'enzyme';
 import * as React from 'react';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {HeaderBar} from './header-bar';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
+describe('describe header bar', () => {
+  it('header bar snapshot', () => {
+    const headerBar = shallow(
+      <HeaderBar
+        active={'load-data'}
+        hideLegacy={false}
+        goToLoadDataView={() => {}}
+      />);
+    expect(headerBar).toMatchSnapshot();
+  });
+});
 
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
diff --git a/web-console/src/components/header-bar.tsx b/web-console/src/components/header-bar/header-bar.tsx
similarity index 95%
rename from web-console/src/components/header-bar.tsx
rename to web-console/src/components/header-bar/header-bar.tsx
index 78f684c..acc722c 100644
--- a/web-console/src/components/header-bar.tsx
+++ b/web-console/src/components/header-bar/header-bar.tsx
@@ -33,17 +33,17 @@ import { IconNames } from '@blueprintjs/icons';
 import classNames from 'classnames';
 import * as React from 'react';
 
-import { AboutDialog } from '../dialogs/about-dialog';
-import { CoordinatorDynamicConfigDialog } from '../dialogs/coordinator-dynamic-config';
-import { OverlordDynamicConfigDialog } from '../dialogs/overlord-dynamic-config';
-import { getWikipediaSpec } from '../utils/example-ingestion-spec';
+import { AboutDialog } from '../../dialogs/about-dialog/about-dialog';
+import { CoordinatorDynamicConfigDialog } from '../../dialogs/coordinator-dynamic-config/coordinator-dynamic-config';
+import { OverlordDynamicConfigDialog } from '../../dialogs/overlord-dynamic-config/overlord-dynamic-config';
+import { getWikipediaSpec } from '../../utils/example-ingestion-spec';
 import {
   DRUID_DOCS,
   DRUID_GITHUB,
   DRUID_USER_GROUP,
   LEGACY_COORDINATOR_CONSOLE,
   LEGACY_OVERLORD_CONSOLE
-} from '../variables';
+} from '../../variables';
 
 import './header-bar.scss';
 
diff --git a/web-console/src/components/auto-form.scss b/web-console/src/components/index.ts
similarity index 50%
rename from web-console/src/components/auto-form.scss
rename to web-console/src/components/index.ts
index a5b4ca2..0acf625 100644
--- a/web-console/src/components/auto-form.scss
+++ b/web-console/src/components/index.ts
@@ -16,26 +16,21 @@
  * limitations under the License.
  */
 
-.auto-form {
-  .ace_scroller {
-    background-color: #212c36;
-  }
-
-  // Popover in info label
-  label.bp3-label {
-    position: relative;
-
-    .bp3-text-muted {
-      position: absolute;
-      right: 0;
-
-      .bp3-popover-wrapper {
-        display: inline;
-
-        .bp3-popover-target {
-          display: inline;
-        }
-      }
-    }
-  }
-}
+export * from './action-cell/action-cell';
+export * from './array-input/array-input';
+export * from './auto-form/auto-form';
+export * from './center-message/center-message';
+export * from './external-link/external-link';
+export * from './header-bar/header-bar';
+export * from './json-collapse/json-collapse';
+export * from './json-input/json-input';
+export * from './loader/loader';
+export * from './menu-checkbox/menu-checkbox';
+export * from './null-table-cell/null-table-cell';
+export * from './rule-editor/rule-editor';
+export * from './show-json/show-json';
+export * from './show-log/show-log';
+export * from './sql-control/sql-control';
+export * from './table-column/table-column-selection';
+export * from './view-control-bar/view-control-bar';
+export * from './clearable-input/clearable-input';
diff --git a/web-console/src/components/json-collapse/__snapshots__/json-collapse.spec.tsx.snap b/web-console/src/components/json-collapse/__snapshots__/json-collapse.spec.tsx.snap
new file mode 100644
index 0000000..88bf309
--- /dev/null
+++ b/web-console/src/components/json-collapse/__snapshots__/json-collapse.spec.tsx.snap
@@ -0,0 +1,29 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe json collapse  json collapse snapshot 1`] = `
+<div
+  class="json-collapse"
+>
+  <button
+    class="bp3-button bp3-minimal"
+    type="button"
+  >
+    <span
+      class="bp3-button-text"
+    >
+      test
+    </span>
+  </button>
+  <div>
+    <div
+      class="bp3-collapse"
+    >
+      <div
+        aria-hidden="false"
+        class="bp3-collapse-body"
+        style="transform: translateY(-0px);"
+      />
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/json-collapse/json-collapse.spec.tsx
similarity index 63%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/json-collapse/json-collapse.spec.tsx
index 0a9c102..7efef6e 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/json-collapse/json-collapse.spec.tsx
@@ -16,21 +16,21 @@
  * limitations under the License.
  */
 
+import {nullableTypeAnnotation} from '@babel/types';
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {JSONCollapse} from './json-collapse';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
 
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe json collapse ', () => {
+  it('json collapse snapshot', () => {
+    const jsonCollapse =
+    <JSONCollapse
+      buttonText={'test'}
+      stringValue={JSON.stringify({ name : 'test' })}
+    />;
+    const { container, getByText } = render(jsonCollapse);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/json-collapse.tsx b/web-console/src/components/json-collapse/json-collapse.tsx
similarity index 100%
rename from web-console/src/components/json-collapse.tsx
rename to web-console/src/components/json-collapse/json-collapse.tsx
diff --git a/web-console/src/components/json-input/__snapshots__/json-collapse.spec.tsx.snap b/web-console/src/components/json-input/__snapshots__/json-collapse.spec.tsx.snap
new file mode 100644
index 0000000..9022a26
--- /dev/null
+++ b/web-console/src/components/json-input/__snapshots__/json-collapse.spec.tsx.snap
@@ -0,0 +1,93 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe json input json input snapshot 1`] = `
+<div
+  class=" ace_editor ace-tm"
+  id="ace-editor"
+  style="width: 100%; height: 8vh;"
+>
+  <textarea
+    autocapitalize="off"
+    autocorrect="off"
+    class="ace_text-input"
+    spellcheck="false"
+    style="opacity: 0;"
+    wrap="off"
+  />
+  <div
+    aria-hidden="true"
+    class="ace_gutter"
+    style="display: none;"
+  >
+    <div
+      class="ace_layer ace_gutter-layer ace_folding-enabled"
+    />
+    <div
+      class="ace_gutter-active-line"
+    />
+  </div>
+  <div
+    class="ace_scroller"
+  >
+    <div
+      class="ace_content"
+    >
+      <div
+        class="ace_layer ace_print-margin-layer"
+      >
+        <div
+          class="ace_print-margin"
+          style="left: 4px; visibility: hidden;"
+        />
+      </div>
+      <div
+        class="ace_layer ace_marker-layer"
+      />
+      <div
+        class="ace_layer ace_text-layer"
+        style="padding: 0px 4px;"
+      />
+      <div
+        class="ace_layer ace_marker-layer"
+      />
+      <div
+        class="ace_layer ace_cursor-layer ace_hidden-cursors"
+      >
+        <div
+          class="ace_cursor"
+        />
+      </div>
+    </div>
+  </div>
+  <div
+    class="ace_scrollbar ace_scrollbar-v"
+    style="display: none; width: 20px;"
+  >
+    <div
+      class="ace_scrollbar-inner"
+      style="width: 20px;"
+    />
+  </div>
+  <div
+    class="ace_scrollbar ace_scrollbar-h"
+    style="display: none; height: 20px;"
+  >
+    <div
+      class="ace_scrollbar-inner"
+      style="height: 20px;"
+    />
+  </div>
+  <div
+    style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
+  >
+    <div
+      style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+    />
+    <div
+      style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+    >
+      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/json-input/json-collapse.spec.tsx
similarity index 67%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/json-input/json-collapse.spec.tsx
index 0a9c102..a3fd7e3 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/json-input/json-collapse.spec.tsx
@@ -17,20 +17,18 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {JSONInput} from './json-input';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
-
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe json input', () => {
+  it('json input snapshot', () => {
+    const jsonCollapse =
+    <JSONInput
+      onChange={(newJSONValue: any) => {}}
+      value={'test'}
+    />;
+    const { container, getByText } = render(jsonCollapse);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/json-input.tsx b/web-console/src/components/json-input/json-input.tsx
similarity index 99%
rename from web-console/src/components/json-input.tsx
rename to web-console/src/components/json-input/json-input.tsx
index 067214bb..2fc7f81 100644
--- a/web-console/src/components/json-input.tsx
+++ b/web-console/src/components/json-input/json-input.tsx
@@ -19,7 +19,7 @@
 import * as React from 'react';
 import AceEditor from 'react-ace';
 
-import { parseStringToJSON, stringifyJSON, validJson } from '../utils';
+import { parseStringToJSON, stringifyJSON, validJson } from '../../utils';
 
 interface JSONInputProps extends React.Props<any> {
   onChange: (newJSONValue: any) => void;
diff --git a/web-console/src/components/loader/__snapshots__/loader.spec.tsx.snap b/web-console/src/components/loader/__snapshots__/loader.spec.tsx.snap
new file mode 100644
index 0000000..5568481
--- /dev/null
+++ b/web-console/src/components/loader/__snapshots__/loader.spec.tsx.snap
@@ -0,0 +1,42 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe loader loader snapshot 1`] = `
+<div
+  class="loader"
+>
+  <div
+    class="loader-logo"
+  >
+    <svg
+      viewBox="0 0 100 100"
+    >
+      <path
+        class="one"
+        d="M54.2,69.8h-2.7c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h2.7c11.5,0,23.8-7.4,23.8-23.7
+          c0-9.1-6.9-15.8-16.4-15.8H38c-0.7,0-1.3-0.6-1.3-1.3s0.6-1.3,1.3-1.3h23.6c5.3,0,10.1,1.9,13.6,5.3c3.5,3.4,5.4,8,5.4,13.1
+          c0,6.6-2.3,13-6.3,17.7C69.5,66.8,62.5,69.8,54.2,69.8z"
+      />
+      <path
+        class="two"
+        d="M55.7,59.5h-26c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h26c7.5,0,11.5-5.8,11.5-11.5
+            c0-4.2-3.2-7.3-7.7-7.3h-26c-0.7,0-1.3-0.6-1.3-1.3s0.6-1.3,1.3-1.3h26c5.9,0,10.3,4.3,10.3,9.9c0,3.7-1.3,7.2-3.7,9.8
+            C63.5,58,59.9,59.5,55.7,59.5z"
+      />
+      <path
+        class="three"
+        d="M27.2,38h-6.3c-0.7,0-1.3-0.6-1.3-1.3s0.6-1.3,1.3-1.3h6.3c0.7,0,1.3,0.6,1.3,1.3S27.9,38,27.2,38z"
+      />
+      <path
+        class="four"
+        d="M45.1,69.8h-5.8c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h5.8c0.7,0,1.3,0.6,1.3,1.3
+            C46.4,69.2,45.8,69.8,45.1,69.8z"
+      />
+    </svg>
+    <div
+      class="label"
+    >
+      test
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/loader.scss b/web-console/src/components/loader/loader.scss
similarity index 100%
rename from web-console/src/components/loader.scss
rename to web-console/src/components/loader/loader.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/loader/loader.spec.tsx
similarity index 70%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/loader/loader.spec.tsx
index 0a9c102..4f1907c 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/loader/loader.spec.tsx
@@ -17,20 +17,18 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import { Loader} from './loader';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
-
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe loader', () => {
+  it('loader snapshot', () => {
+    const loader =
+    <Loader
+      loading={true}
+      loadingText={'test'}
+    />;
+    const { container, getByText } = render(loader);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/loader.tsx b/web-console/src/components/loader/loader.tsx
similarity index 100%
rename from web-console/src/components/loader.tsx
rename to web-console/src/components/loader/loader.tsx
diff --git a/web-console/src/components/menu-checkbox/__snapshots__/menu-checkbox.spec.tsx.snap b/web-console/src/components/menu-checkbox/__snapshots__/menu-checkbox.spec.tsx.snap
new file mode 100644
index 0000000..fd9dc4e
--- /dev/null
+++ b/web-console/src/components/menu-checkbox/__snapshots__/menu-checkbox.spec.tsx.snap
@@ -0,0 +1,18 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe menuCheckBox  menuCheckbox snapshot 1`] = `
+<li
+  class="menu-checkbox"
+>
+  <label
+    class="bp3-control bp3-checkbox"
+  >
+    <input
+      type="checkbox"
+    />
+    <span
+      class="bp3-control-indicator"
+    />
+  </label>
+</li>
+`;
diff --git a/web-console/src/components/menu-checkbox.scss b/web-console/src/components/menu-checkbox/menu-checkbox.scss
similarity index 100%
rename from web-console/src/components/menu-checkbox.scss
rename to web-console/src/components/menu-checkbox/menu-checkbox.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/menu-checkbox/menu-checkbox.spec.tsx
similarity index 71%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/menu-checkbox/menu-checkbox.spec.tsx
index 0a9c102..6ca6efe 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/menu-checkbox/menu-checkbox.spec.tsx
@@ -17,20 +17,15 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {MenuCheckbox} from './menu-checkbox';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
-
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe menuCheckBox ', () => {
+  it('menuCheckbox snapshot', () => {
+    const menuCheckbox =
+    <MenuCheckbox/>;
+    const { container, getByText } = render(menuCheckbox);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/menu-checkbox.tsx b/web-console/src/components/menu-checkbox/menu-checkbox.tsx
similarity index 100%
copy from web-console/src/components/menu-checkbox.tsx
copy to web-console/src/components/menu-checkbox/menu-checkbox.tsx
diff --git a/web-console/src/components/null-table-cell/__snapshots__/null-table-cell.spec.tsx.snap b/web-console/src/components/null-table-cell/__snapshots__/null-table-cell.spec.tsx.snap
new file mode 100644
index 0000000..8452cb7
--- /dev/null
+++ b/web-console/src/components/null-table-cell/__snapshots__/null-table-cell.spec.tsx.snap
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe nullTable nullTable snapshot 1`] = `test`;
diff --git a/web-console/src/components/null-table-cell.scss b/web-console/src/components/null-table-cell/null-table-cell.scss
similarity index 100%
rename from web-console/src/components/null-table-cell.scss
rename to web-console/src/components/null-table-cell/null-table-cell.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/null-table-cell/null-table-cell.spec.tsx
similarity index 66%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/null-table-cell/null-table-cell.spec.tsx
index 0a9c102..83feffa 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/null-table-cell/null-table-cell.spec.tsx
@@ -17,20 +17,19 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {NullTableCell} from './null-table-cell';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
-
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe nullTable', () => {
+  it('nullTable snapshot', () => {
+    const nullTableCell =
+    <NullTableCell
+      value={'test'}
+      unparseable={false}
+      timestamp={false}
+    />
+    const { container, getByText } = render(nullTableCell);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/null-table-cell.tsx b/web-console/src/components/null-table-cell/null-table-cell.tsx
similarity index 99%
copy from web-console/src/components/null-table-cell.tsx
copy to web-console/src/components/null-table-cell/null-table-cell.tsx
index 01eeb7d..c8d6758 100644
--- a/web-console/src/components/null-table-cell.tsx
+++ b/web-console/src/components/null-table-cell/null-table-cell.tsx
@@ -1,3 +1,4 @@
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
diff --git a/web-console/src/components/rule-editor/__snapshots__/rule-editor.spec.tsx.snap b/web-console/src/components/rule-editor/__snapshots__/rule-editor.spec.tsx.snap
new file mode 100644
index 0000000..43ab28c
--- /dev/null
+++ b/web-console/src/components/rule-editor/__snapshots__/rule-editor.spec.tsx.snap
@@ -0,0 +1,220 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe rule editor rule editor snapshot 1`] = `
+<div
+  class="rule-editor"
+>
+  <div
+    class="title"
+  >
+    <button
+      class="bp3-button bp3-minimal left"
+      type="button"
+    >
+      <span
+        class="bp3-button-text"
+      >
+        loadForever
+      </span>
+      <span
+        class="bp3-icon bp3-icon-caret-down"
+        icon="caret-down"
+      >
+        <svg
+          data-icon="caret-down"
+          height="16"
+          viewBox="0 0 16 16"
+          width="16"
+        >
+          <desc>
+            caret-down
+          </desc>
+          <path
+            d="M12 6.5c0-.28-.22-.5-.5-.5h-7a.495.495 0 0 0-.37.83l3.5 4c.09.1.22.17.37.17s.28-.07.37-.17l3.5-4c.08-.09.13-.2.13-.33z"
+            fill-rule="evenodd"
+          />
+        </svg>
+      </span>
+    </button>
+    <div
+      class="spacer"
+    />
+    <button
+      class="bp3-button bp3-minimal"
+      type="button"
+    >
+      <span
+        class="bp3-icon bp3-icon-trash"
+        icon="trash"
+      >
+        <svg
+          data-icon="trash"
+          height="16"
+          viewBox="0 0 16 16"
+          width="16"
+        >
+          <desc>
+            trash
+          </desc>
+          <path
+            d="M14.49 3.99h-13c-.28 0-.5.22-.5.5s.22.5.5.5h.5v10c0 .55.45 1 1 1h10c.55 0 1-.45 1-1v-10h.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5zm-8.5 9c0 .55-.45 1-1 1s-1-.45-1-1v-6c0-.55.45-1 1-1s1 .45 1 1v6zm3 0c0 .55-.45 1-1 1s-1-.45-1-1v-6c0-.55.45-1 1-1s1 .45 1 1v6zm3 0c0 .55-.45 1-1 1s-1-.45-1-1v-6c0-.55.45-1 1-1s1 .45 1 1v6zm2-12h-4c0-.55-.45-1-1-1h-2c-.55 0-1 .45-1 1h-4c-.55 0-1 .45-1 1v1h14v-1c0-.55-.45-1-1-1z"
+            fill-rule="evenodd"
+          />
+        </svg>
+      </span>
+    </button>
+  </div>
+  <div
+    class="bp3-collapse"
+    style="height: auto; overflow-y: visible; transition: none;"
+  >
+    <div
+      aria-hidden="false"
+      class="bp3-collapse-body"
+      style="transform: translateY(0); transition: none;"
+    >
+      <div
+        class="bp3-card bp3-elevation-0"
+      >
+        <div
+          class="bp3-form-group"
+        >
+          <div
+            class="bp3-form-content"
+          >
+            <div
+              class="bp3-control-group"
+            >
+              <div
+                class="bp3-html-select"
+              >
+                <select>
+                  <option
+                    value="load"
+                  >
+                    Load
+                  </option>
+                  <option
+                    value="drop"
+                  >
+                    Drop
+                  </option>
+                  <option
+                    value="broadcast"
+                  >
+                    Broadcast
+                  </option>
+                </select>
+                <span
+                  class="bp3-icon bp3-icon-double-caret-vertical"
+                  icon="double-caret-vertical"
+                >
+                  <svg
+                    data-icon="double-caret-vertical"
+                    height="16"
+                    viewBox="0 0 16 16"
+                    width="16"
+                  >
+                    <desc>
+                      double-caret-vertical
+                    </desc>
+                    <path
+                      d="M5 7h6a1.003 1.003 0 0 0 .71-1.71l-3-3C8.53 2.11 8.28 2 8 2s-.53.11-.71.29l-3 3A1.003 1.003 0 0 0 5 7zm6 2H5a1.003 1.003 0 0 0-.71 1.71l3 3c.18.18.43.29.71.29s.53-.11.71-.29l3-3A1.003 1.003 0 0 0 11 9z"
+                      fill-rule="evenodd"
+                    />
+                  </svg>
+                </span>
+              </div>
+              <div
+                class="bp3-html-select"
+              >
+                <select>
+                  <option
+                    value="Forever"
+                  >
+                    forever
+                  </option>
+                  <option
+                    value="ByPeriod"
+                  >
+                    by period
+                  </option>
+                  <option
+                    value="ByInterval"
+                  >
+                    by interval
+                  </option>
+                </select>
+                <span
+                  class="bp3-icon bp3-icon-double-caret-vertical"
+                  icon="double-caret-vertical"
+                >
+                  <svg
+                    data-icon="double-caret-vertical"
+                    height="16"
+                    viewBox="0 0 16 16"
+                    width="16"
+                  >
+                    <desc>
+                      double-caret-vertical
+                    </desc>
+                    <path
+                      d="M5 7h6a1.003 1.003 0 0 0 .71-1.71l-3-3C8.53 2.11 8.28 2 8 2s-.53.11-.71.29l-3 3A1.003 1.003 0 0 0 5 7zm6 2H5a1.003 1.003 0 0 0-.71 1.71l3 3c.18.18.43.29.71.29s.53-.11.71-.29l3-3A1.003 1.003 0 0 0 11 9z"
+                      fill-rule="evenodd"
+                    />
+                  </svg>
+                </span>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-form-group"
+        >
+          <div
+            class="bp3-form-content"
+          >
+            <div
+              class="bp3-form-group right"
+            >
+              <div
+                class="bp3-form-content"
+              >
+                <button
+                  class="bp3-button bp3-minimal"
+                  type="button"
+                >
+                  <span
+                    class="bp3-icon bp3-icon-plus"
+                    icon="plus"
+                  >
+                    <svg
+                      data-icon="plus"
+                      height="16"
+                      viewBox="0 0 16 16"
+                      width="16"
+                    >
+                      <desc>
+                        plus
+                      </desc>
+                      <path
+                        d="M13 7H9V3c0-.55-.45-1-1-1s-1 .45-1 1v4H3c-.55 0-1 .45-1 1s.45 1 1 1h4v4c0 .55.45 1 1 1s1-.45 1-1V9h4c.55 0 1-.45 1-1s-.45-1-1-1z"
+                        fill-rule="evenodd"
+                      />
+                    </svg>
+                  </span>
+                  <span
+                    class="bp3-button-text"
+                  >
+                    Add a tier
+                  </span>
+                </button>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/rule-editor.scss b/web-console/src/components/rule-editor/rule-editor.scss
similarity index 100%
rename from web-console/src/components/rule-editor.scss
rename to web-console/src/components/rule-editor/rule-editor.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/rule-editor/rule-editor.spec.tsx
similarity index 61%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/rule-editor/rule-editor.spec.tsx
index 0a9c102..e15e58e 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/rule-editor/rule-editor.spec.tsx
@@ -17,20 +17,22 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {Rule, RuleEditor} from './rule-editor';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
-
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe rule editor', () => {
+  it('rule editor snapshot', () => {
+    const ruleEditor =
+    <RuleEditor
+      rule={{type: 'loadForever' }}
+      tiers={['test', 'test', 'test']}
+      onChange={(newRule: Rule) => null}
+      onDelete={() => null}
+      moveUp={null}
+      moveDown={null}
+    />;
+    const { container, getByText } = render(ruleEditor);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/rule-editor.tsx b/web-console/src/components/rule-editor/rule-editor.tsx
similarity index 100%
rename from web-console/src/components/rule-editor.tsx
rename to web-console/src/components/rule-editor/rule-editor.tsx
diff --git a/web-console/src/components/show-json/__snapshots__/show-json.spec.tsx.snap b/web-console/src/components/show-json/__snapshots__/show-json.spec.tsx.snap
new file mode 100644
index 0000000..7129c21
--- /dev/null
+++ b/web-console/src/components/show-json/__snapshots__/show-json.spec.tsx.snap
@@ -0,0 +1,54 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe rule editor rule editor snapshot 1`] = `
+<div
+  class="show-json"
+>
+  <div
+    class="top-actions"
+  >
+    <div
+      class="bp3-button-group right-buttons"
+    >
+      <button
+        class="bp3-button bp3-minimal"
+        type="button"
+      >
+        <span
+          class="bp3-button-text"
+        >
+          Save
+        </span>
+      </button>
+      <button
+        class="bp3-button bp3-minimal"
+        type="button"
+      >
+        <span
+          class="bp3-button-text"
+        >
+          Copy
+        </span>
+      </button>
+      <button
+        class="bp3-button bp3-minimal"
+        type="button"
+      >
+        <span
+          class="bp3-button-text"
+        >
+          View raw
+        </span>
+      </button>
+    </div>
+  </div>
+  <div
+    class="main-area"
+  >
+    <textarea
+      class="bp3-input"
+      readonly=""
+    />
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/show-json.scss b/web-console/src/components/show-json/show-json.scss
similarity index 100%
rename from web-console/src/components/show-json.scss
rename to web-console/src/components/show-json/show-json.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/show-json/show-json.spec.tsx
similarity index 68%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/show-json/show-json.spec.tsx
index 0a9c102..3ef08f8 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/show-json/show-json.spec.tsx
@@ -17,20 +17,19 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {ShowJson} from './show-json';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
 
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe rule editor', () => {
+  it('rule editor snapshot', () => {
+    const showJson =
+      <ShowJson
+        endpoint={'test'}
+        downloadFilename={'test'}
+      />;
+    const { container, getByText } = render(showJson);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/show-json.tsx b/web-console/src/components/show-json/show-json.tsx
similarity index 95%
rename from web-console/src/components/show-json.tsx
rename to web-console/src/components/show-json/show-json.tsx
index ebc4bfc..aa255b5 100644
--- a/web-console/src/components/show-json.tsx
+++ b/web-console/src/components/show-json/show-json.tsx
@@ -21,9 +21,9 @@ import axios from 'axios';
 import * as React from 'react';
 import * as CopyToClipboard from 'react-copy-to-clipboard';
 
-import { AppToaster } from '../singletons/toaster';
-import { UrlBaser } from '../singletons/url-baser';
-import { downloadFile } from '../utils';
+import { AppToaster } from '../../singletons/toaster';
+import { UrlBaser } from '../../singletons/url-baser';
+import { downloadFile } from '../../utils';
 
 import './show-json.scss';
 
diff --git a/web-console/src/components/show-log/__snapshots__/show-log.spec.tsx.snap b/web-console/src/components/show-log/__snapshots__/show-log.spec.tsx.snap
new file mode 100644
index 0000000..37f75bc
--- /dev/null
+++ b/web-console/src/components/show-log/__snapshots__/show-log.spec.tsx.snap
@@ -0,0 +1,54 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe show log describe show log 1`] = `
+<div
+  class="show-log"
+>
+  <div
+    class="top-actions"
+  >
+    <div
+      class="bp3-button-group right-buttons"
+    >
+      <button
+        class="bp3-button bp3-minimal"
+        type="button"
+      >
+        <span
+          class="bp3-button-text"
+        >
+          Save
+        </span>
+      </button>
+      <button
+        class="bp3-button bp3-minimal"
+        type="button"
+      >
+        <span
+          class="bp3-button-text"
+        >
+          Copy
+        </span>
+      </button>
+      <button
+        class="bp3-button bp3-minimal"
+        type="button"
+      >
+        <span
+          class="bp3-button-text"
+        >
+          View full log
+        </span>
+      </button>
+    </div>
+  </div>
+  <div
+    class="main-area"
+  >
+    <textarea
+      class="bp3-input"
+      readonly=""
+    />
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/show-log.scss b/web-console/src/components/show-log/show-log.scss
similarity index 100%
rename from web-console/src/components/show-log.scss
rename to web-console/src/components/show-log/show-log.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/show-log/show-log.spec.tsx
similarity index 69%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/show-log/show-log.spec.tsx
index 0a9c102..ff418ed 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/show-log/show-log.spec.tsx
@@ -17,20 +17,19 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {ShowLog} from './show-log';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
 
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe show log', () => {
+  it('describe show log', () => {
+    const showLog =
+      <ShowLog
+        endpoint={'test'}
+        downloadFilename={'test'}
+      />;
+    const { container, getByText } = render(showLog);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/show-log.tsx b/web-console/src/components/show-log/show-log.tsx
similarity index 95%
rename from web-console/src/components/show-log.tsx
rename to web-console/src/components/show-log/show-log.tsx
index c89e406..e6b5e18 100644
--- a/web-console/src/components/show-log.tsx
+++ b/web-console/src/components/show-log/show-log.tsx
@@ -21,9 +21,9 @@ import axios from 'axios';
 import * as React from 'react';
 import * as CopyToClipboard from 'react-copy-to-clipboard';
 
-import { AppToaster } from '../singletons/toaster';
-import { UrlBaser } from '../singletons/url-baser';
-import { downloadFile } from '../utils';
+import { AppToaster } from '../../singletons/toaster';
+import { UrlBaser } from '../../singletons/url-baser';
+import { downloadFile } from '../../utils';
 
 import './show-log.scss';
 
diff --git a/web-console/src/components/sql-control/__snapshots__/sql-control.spec.tsx.snap b/web-console/src/components/sql-control/__snapshots__/sql-control.spec.tsx.snap
new file mode 100644
index 0000000..1fb9aa3
--- /dev/null
+++ b/web-console/src/components/sql-control/__snapshots__/sql-control.spec.tsx.snap
@@ -0,0 +1,172 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe sql control sql control snapshot 1`] = `
+<div
+  class="sql-control"
+>
+  <div
+    class=" ace_editor ace-solarized-dark ace_dark ace_focus"
+    id="ace-editor"
+    style="width: 100%; height: 30vh; font-size: 14px;"
+  >
+    <textarea
+      autocapitalize="off"
+      autocorrect="off"
+      class="ace_text-input"
+      spellcheck="false"
+      style="opacity: 0; position: fixed; top: 0px;"
+      wrap="off"
+    />
+    <div
+      aria-hidden="true"
+      class="ace_gutter"
+    >
+      <div
+        class="ace_layer ace_gutter-layer ace_folding-enabled"
+      />
+      <div
+        class="ace_gutter-active-line"
+      />
+    </div>
+    <div
+      class="ace_scroller"
+    >
+      <div
+        class="ace_content"
+      >
+        <div
+          class="ace_layer ace_print-margin-layer"
+        >
+          <div
+            class="ace_print-margin"
+            style="left: 4px; visibility: hidden;"
+          />
+        </div>
+        <div
+          class="ace_layer ace_marker-layer"
+        />
+        <div
+          class="ace_layer ace_text-layer"
+          style="padding: 0px 4px;"
+        />
+        <div
+          class="ace_layer ace_marker-layer"
+        />
+        <div
+          class="ace_layer ace_cursor-layer"
+        >
+          <div
+            class="ace_cursor"
+          />
+        </div>
+      </div>
+    </div>
+    <div
+      class="ace_scrollbar ace_scrollbar-v"
+      style="display: none; width: 20px;"
+    >
+      <div
+        class="ace_scrollbar-inner"
+        style="width: 20px;"
+      />
+    </div>
+    <div
+      class="ace_scrollbar ace_scrollbar-h"
+      style="display: none; height: 20px;"
+    >
+      <div
+        class="ace_scrollbar-inner"
+        style="height: 20px;"
+      />
+    </div>
+    <div
+      style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
+    >
+      <div
+        style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+      />
+      <div
+        style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+      >
+        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+      </div>
+    </div>
+  </div>
+  <div
+    class="buttons"
+  >
+    <div
+      class="bp3-button-group"
+    >
+      <button
+        class="bp3-button"
+        type="button"
+      >
+        <span
+          class="bp3-icon bp3-icon-caret-right"
+          icon="caret-right"
+        >
+          <svg
+            data-icon="caret-right"
+            height="16"
+            viewBox="0 0 16 16"
+            width="16"
+          >
+            <desc>
+              caret-right
+            </desc>
+            <path
+              d="M11 8c0-.15-.07-.28-.17-.37l-4-3.5A.495.495 0 0 0 6 4.5v7a.495.495 0 0 0 .83.37l4-3.5c.1-.09.17-.22.17-.37z"
+              fill-rule="evenodd"
+            />
+          </svg>
+        </span>
+        <span
+          class="bp3-button-text"
+        >
+          Run with limit
+        </span>
+      </button>
+      <span
+        class="bp3-popover-wrapper"
+      >
+        <span
+          class="bp3-popover-target"
+        >
+          <button
+            class="bp3-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-more"
+              icon="more"
+            >
+              <svg
+                data-icon="more"
+                height="16"
+                viewBox="0 0 16 16"
+                width="16"
+              >
+                <desc>
+                  more
+                </desc>
+                <path
+                  d="M2 6.03a2 2 0 1 0 0 4 2 2 0 1 0 0-4zM14 6.03a2 2 0 1 0 0 4 2 2 0 1 0 0-4zM8 6.03a2 2 0 1 0 0 4 2 2 0 1 0 0-4z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </span>
+      </span>
+    </div>
+    <span
+      class="query-elapsed"
+    >
+       Last query took 
+      0.00
+       seconds
+    </span>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/sql-control.scss b/web-console/src/components/sql-control/sql-control.scss
similarity index 100%
rename from web-console/src/components/sql-control.scss
rename to web-console/src/components/sql-control/sql-control.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/sql-control/sql-control.spec.tsx
similarity index 62%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/sql-control/sql-control.spec.tsx
index 0a9c102..73f7902 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/sql-control/sql-control.spec.tsx
@@ -17,20 +17,21 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {SqlControl} from './sql-control';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
 
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe sql control', () => {
+  it('sql control snapshot', () => {
+    const sqlControl =
+      <SqlControl
+        initSql={'test'}
+        onRun={(query: string, bypassCache: boolean, wrapQuery: boolean) => {}}
+        onExplain={(sqlQuery: string) => {}}
+        queryElapsed={2}
+      />
+    const { container, getByText } = render(sqlControl);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/sql-control.tsx b/web-console/src/components/sql-control/sql-control.tsx
similarity index 97%
rename from web-console/src/components/sql-control.tsx
rename to web-console/src/components/sql-control/sql-control.tsx
index e34a3f3..06f7e80 100644
--- a/web-console/src/components/sql-control.tsx
+++ b/web-console/src/components/sql-control/sql-control.tsx
@@ -38,14 +38,15 @@ import * as React from 'react';
 import AceEditor from 'react-ace';
 import * as ReactDOMServer from 'react-dom/server';
 
-import { SQLFunctionDoc } from '../../lib/sql-function-doc';
-import { AppToaster } from '../singletons/toaster';
-import { DRUID_DOCS_RUNE, DRUID_DOCS_SQL } from '../variables';
+import { SQLFunctionDoc } from '../../../lib/sql-function-doc';
+import { AppToaster } from '../../singletons/toaster';
+import { DRUID_DOCS_RUNE, DRUID_DOCS_SQL } from '../../variables';
 
-import { MenuCheckbox } from './menu-checkbox';
+import { MenuCheckbox } from './../menu-checkbox/menu-checkbox';
 
 import './sql-control.scss';
 
+
 function validHjson(query: string) {
   try {
     Hjson.parse(query);
diff --git a/web-console/src/components/table-column/__snapshots__/table-column-selection.spec.tsx.snap b/web-console/src/components/table-column/__snapshots__/table-column-selection.spec.tsx.snap
new file mode 100644
index 0000000..ebd1a0e
--- /dev/null
+++ b/web-console/src/components/table-column/__snapshots__/table-column-selection.spec.tsx.snap
@@ -0,0 +1,41 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe table column table column snapshot 1`] = `
+<span
+  class="bp3-popover-wrapper table-column-selection"
+>
+  <span
+    class="bp3-popover-target"
+  >
+    <button
+      class="bp3-button"
+      type="button"
+    >
+      <span
+        class="bp3-button-text"
+      >
+        Columns
+      </span>
+      <span
+        class="bp3-icon bp3-icon-caret-down"
+        icon="caret-down"
+      >
+        <svg
+          data-icon="caret-down"
+          height="16"
+          viewBox="0 0 16 16"
+          width="16"
+        >
+          <desc>
+            caret-down
+          </desc>
+          <path
+            d="M12 6.5c0-.28-.22-.5-.5-.5h-7a.495.495 0 0 0-.37.83l3.5 4c.09.1.22.17.37.17s.28-.07.37-.17l3.5-4c.08-.09.13-.2.13-.33z"
+            fill-rule="evenodd"
+          />
+        </svg>
+      </span>
+    </button>
+  </span>
+</span>
+`;
diff --git a/web-console/src/components/table-column-selection.scss b/web-console/src/components/table-column/table-column-selection.scss
similarity index 100%
rename from web-console/src/components/table-column-selection.scss
rename to web-console/src/components/table-column/table-column-selection.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/table-column/table-column-selection.spec.tsx
similarity index 62%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/table-column/table-column-selection.spec.tsx
index 0a9c102..b321963 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/table-column/table-column-selection.spec.tsx
@@ -17,20 +17,19 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import {TableColumnSelection} from './table-column-selection';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
-
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+describe('describe table column', () => {
+  it('table column snapshot', () => {
+    const tableColumn =
+      <TableColumnSelection
+        columns={['a', 'b', 'c']}
+        onChange={(column: string) => {}}
+        tableColumnsHidden={['a', 'b', 'c']}
+      />;
+    const { container, getByText } = render(tableColumn);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/table-column-selection.tsx b/web-console/src/components/table-column/table-column-selection.tsx
similarity index 97%
rename from web-console/src/components/table-column-selection.tsx
rename to web-console/src/components/table-column/table-column-selection.tsx
index 3635d51..aafa95b 100644
--- a/web-console/src/components/table-column-selection.tsx
+++ b/web-console/src/components/table-column/table-column-selection.tsx
@@ -20,7 +20,7 @@ import { Button, Checkbox, FormGroup, Menu, Popover, Position } from '@blueprint
 import { IconNames } from '@blueprintjs/icons';
 import * as React from 'react';
 
-import { MenuCheckbox } from './menu-checkbox';
+import { MenuCheckbox } from '../menu-checkbox/menu-checkbox';
 
 import './table-column-selection.scss';
 
diff --git a/web-console/src/components/view-control-bar/__snapshots__/view-control-bar.spec.tsx.snap b/web-console/src/components/view-control-bar/__snapshots__/view-control-bar.spec.tsx.snap
new file mode 100644
index 0000000..003623a
--- /dev/null
+++ b/web-console/src/components/view-control-bar/__snapshots__/view-control-bar.spec.tsx.snap
@@ -0,0 +1,16 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe view control bar snapshot view control bar snapshot snapshot 1`] = `
+<div
+  class="view-control-bar"
+>
+  <div
+    class="control-label"
+  >
+    A label
+  </div>
+  <div>
+    Hello world
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/view-control-bar.scss b/web-console/src/components/view-control-bar/view-control-bar.scss
similarity index 100%
rename from web-console/src/components/view-control-bar.scss
rename to web-console/src/components/view-control-bar/view-control-bar.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/components/view-control-bar/view-control-bar.spec.tsx
similarity index 65%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/components/view-control-bar/view-control-bar.spec.tsx
index 0a9c102..e4318d3 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/components/view-control-bar/view-control-bar.spec.tsx
@@ -17,20 +17,18 @@
  */
 
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
+import { ViewControlBar } from './view-control-bar';
 
-export class ExternalLink extends React.Component<ExternalLinkProps, {}> {
-  render() {
-    const { href, children } = this.props;
+describe('describe view control bar snapshot', () => {
+  it('view control bar snapshot snapshot', () => {
+    const viewControlBar =
+      <ViewControlBar label="A label">
+        <div>Hello world</div>
+      </ViewControlBar>;
 
-    return <a
-      href={href}
-      target="_blank"
-    >
-      {children}
-    </a>;
-  }
-}
+    const { container, getByText } = render(viewControlBar);
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/components/view-control-bar.tsx b/web-console/src/components/view-control-bar/view-control-bar.tsx
similarity index 100%
copy from web-console/src/components/view-control-bar.tsx
copy to web-console/src/components/view-control-bar/view-control-bar.tsx
diff --git a/web-console/src/console-application.tsx b/web-console/src/console-application.tsx
index ce46672..6cbf625 100644
--- a/web-console/src/console-application.tsx
+++ b/web-console/src/console-application.tsx
@@ -23,21 +23,21 @@ import * as classNames from 'classnames';
 import * as React from 'react';
 import { HashRouter, Route, Switch } from 'react-router-dom';
 
-import { ExternalLink } from './components/external-link';
-import { HeaderActiveTab, HeaderBar } from './components/header-bar';
-import { Loader } from './components/loader';
+import { ExternalLink } from './components/external-link/external-link';
+import { HeaderActiveTab, HeaderBar } from './components/header-bar/header-bar';
+import { Loader } from './components/loader/loader';
 import { AppToaster } from './singletons/toaster';
 import { UrlBaser } from './singletons/url-baser';
 import { QueryManager } from './utils';
 import { DRUID_DOCS_API, DRUID_DOCS_SQL } from './variables';
-import { DatasourcesView } from './views/datasource-view';
-import { HomeView } from './views/home-view';
-import { LoadDataView } from './views/load-data-view';
-import { LookupsView } from './views/lookups-view';
-import { SegmentsView } from './views/segments-view';
-import { ServersView } from './views/servers-view';
-import { SqlView } from './views/sql-view';
-import { TasksView } from './views/tasks-view';
+import { DatasourcesView } from './views/datasource-view/datasource-view';
+import { HomeView } from './views/home-view/home-view';
+import { LoadDataView } from './views/load-data-view/load-data-view';
+import { LookupsView } from './views/lookups-view/lookups-view';
+import { SegmentsView } from './views/segments-view/segments-view';
+import { ServersView } from './views/servers-view/servers-view';
+import { SqlView } from './views/sql-view/sql-view';
+import { TasksView } from './views/task-view/tasks-view';
 
 import './console-application.scss';
 
diff --git a/web-console/src/dialogs/about-dialog/__snapshots__/about-dialog.spec.tsx.snap b/web-console/src/dialogs/about-dialog/__snapshots__/about-dialog.spec.tsx.snap
new file mode 100644
index 0000000..0a94ec7
--- /dev/null
+++ b/web-console/src/dialogs/about-dialog/__snapshots__/about-dialog.spec.tsx.snap
@@ -0,0 +1,145 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe about dialog about dialog snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog"
+      >
+        <div
+          class="bp3-dialog-header"
+        >
+          <span
+            class="bp3-icon bp3-icon-graph"
+            icon="graph"
+          >
+            <svg
+              data-icon="graph"
+              height="20"
+              viewBox="0 0 20 20"
+              width="20"
+            >
+              <desc>
+                graph
+              </desc>
+              <path
+                d="M17.5 4A2.5 2.5 0 0 0 15 6.5c0 .06.01.12.02.18l-1.9.84C12.38 6.6 11.27 6 10 6c-.83 0-1.59.25-2.23.68L4.91 4.14c.05-.21.09-.42.09-.64a2.5 2.5 0 0 0-5 0A2.5 2.5 0 0 0 2.5 6c.42 0 .81-.11 1.16-.3l2.79 2.48C6.17 8.73 6 9.34 6 10c0 1.41.73 2.64 1.83 3.35l-.56 1.67A2.498 2.498 0 0 0 5 17.5a2.5 2.5 0 0 0 5 0c0-.74-.32-1.39-.83-1.85l.56-1.68c.09.01.18.03.27.03 2.21 0 4-1.79 4-4 0-.22-.03-.44-.07-.65l2.02-.9c.43.34.96.55 1.55.55a2.5 2.5 0 0 0 0-5z"
+                fill-rule="evenodd"
+              />
+            </svg>
+          </span>
+          <h4
+            class="bp3-heading"
+          >
+            Apache Druid
+          </h4>
+          <button
+            aria-label="Close"
+            class="bp3-button bp3-minimal bp3-dialog-close-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-small-cross"
+              icon="small-cross"
+            >
+              <svg
+                data-icon="small-cross"
+                height="20"
+                viewBox="0 0 20 20"
+                width="20"
+              >
+                <desc>
+                  small-cross
+                </desc>
+                <path
+                  d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L11.41 10z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+        <div
+          class="bp3-dialog-body"
+        >
+          <p>
+            <strong>
+              Apache Druid (incubating) is a high performance real-time analytics database.
+            </strong>
+          </p>
+          <p>
+            For help and support with Druid, please refer to the 
+            <a
+              href="http://druid.io/community/"
+              target="_blank"
+            >
+              community page
+            </a>
+             and the 
+            <a
+              href="https://groups.google.com/forum/#!forum/druid-user"
+              target="_blank"
+            >
+              user groups
+            </a>
+            .
+          </p>
+          <p>
+            Druid is made with ❤️ by a community of passionate developers. To contribute, join in the discussion on the 
+            <a
+              href="https://lists.apache.org/list.html?dev@druid.apache.org"
+              target="_blank"
+            >
+              developer group
+            </a>
+            .
+          </p>
+        </div>
+        <div
+          class="bp3-dialog-footer"
+        >
+          <div
+            class="bp3-dialog-footer-actions"
+          >
+            <button
+              class="bp3-button"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Close
+              </span>
+            </button>
+            <a
+              class="bp3-button bp3-intent-primary"
+              href="http://druid.io"
+              role="button"
+              tabindex="0"
+              target="_blank"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Visit Druid
+              </span>
+            </a>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/action-cell.tsx b/web-console/src/dialogs/about-dialog/about-dialog.spec.tsx
similarity index 67%
copy from web-console/src/components/action-cell.tsx
copy to web-console/src/dialogs/about-dialog/about-dialog.spec.tsx
index e37b2c9..0380167 100644
--- a/web-console/src/components/action-cell.tsx
+++ b/web-console/src/dialogs/about-dialog/about-dialog.spec.tsx
@@ -16,21 +16,20 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
 
-import './action-cell.scss';
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export interface ActionCellProps extends React.Props<any> {
-}
+import {AboutDialog} from './about-dialog';
 
-export class ActionCell extends React.Component<ActionCellProps, {}> {
-  constructor(props: ActionCellProps, context: any) {
-    super(props, context);
-  }
 
-  render() {
-    return <div className="action-cell">
-      {this.props.children}
-    </div>;
-  }
-}
+describe('describe about dialog', () => {
+  it('about dialog snapshot', () => {
+    const aboutDialog =
+     <AboutDialog
+       onClose={() => null}
+     />;
+    const { container, getByText } = render(aboutDialog, { container: document.body });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/dialogs/about-dialog.tsx b/web-console/src/dialogs/about-dialog/about-dialog.tsx
similarity index 95%
rename from web-console/src/dialogs/about-dialog.tsx
rename to web-console/src/dialogs/about-dialog/about-dialog.tsx
index 10992a7..a863941 100644
--- a/web-console/src/dialogs/about-dialog.tsx
+++ b/web-console/src/dialogs/about-dialog/about-dialog.tsx
@@ -20,8 +20,8 @@ import { AnchorButton, Button, Classes, Dialog, Intent } from '@blueprintjs/core
 import { IconNames } from '@blueprintjs/icons';
 import * as React from 'react';
 
-import { ExternalLink } from '../components/external-link';
-import { DRUID_COMMUNITY, DRUID_DEVELOPER_GROUP, DRUID_USER_GROUP, DRUID_WEBSITE } from '../variables';
+import { ExternalLink } from '../../components/external-link/external-link';
+import { DRUID_COMMUNITY, DRUID_DEVELOPER_GROUP, DRUID_USER_GROUP, DRUID_WEBSITE } from '../../variables';
 
 export interface AboutDialogProps extends React.Props<any> {
   onClose: () => void;
diff --git a/web-console/src/dialogs/async-action-dialog/__snapshots__/async-action-dialog.spec.tsx.snap b/web-console/src/dialogs/async-action-dialog/__snapshots__/async-action-dialog.spec.tsx.snap
new file mode 100644
index 0000000..a10ad03
--- /dev/null
+++ b/web-console/src/dialogs/async-action-dialog/__snapshots__/async-action-dialog.spec.tsx.snap
@@ -0,0 +1,56 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe async action dialog async action dialog snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog bp3-alert async-alert-dialog"
+      >
+        <div
+          class="bp3-alert-body"
+        >
+          <div
+            class="bp3-alert-contents"
+          />
+        </div>
+        <div
+          class="bp3-alert-footer"
+        >
+          <button
+            class="bp3-button"
+            type="button"
+          >
+            <span
+              class="bp3-button-text"
+            >
+              test
+            </span>
+          </button>
+          <button
+            class="bp3-button"
+            type="button"
+          >
+            <span
+              class="bp3-button-text"
+            >
+              Cancel
+            </span>
+          </button>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/view-control-bar.tsx b/web-console/src/dialogs/async-action-dialog/async-action-dialog.spec.tsx
similarity index 58%
copy from web-console/src/components/view-control-bar.tsx
copy to web-console/src/dialogs/async-action-dialog/async-action-dialog.spec.tsx
index 679c671..f73396b 100644
--- a/web-console/src/components/view-control-bar.tsx
+++ b/web-console/src/dialogs/async-action-dialog/async-action-dialog.spec.tsx
@@ -16,25 +16,24 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
-
-import './view-control-bar.scss';
 
-export interface ViewControlBarProps {
-  label: string;
-}
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export class ViewControlBar extends React.Component<ViewControlBarProps, {}> {
-  constructor(props: ViewControlBarProps) {
-    super(props);
-  }
+import {AsyncActionDialog} from './async-action-dialog';
 
-  render() {
-    const { label, children } = this.props;
 
-    return <div className="view-control-bar">
-      <div className="control-label">{label}</div>
-      {children}
-    </div>;
-  }
-}
+describe('describe async action dialog', () => {
+  it('async action dialog snapshot', () => {
+    const asyncActionDialog =
+      <AsyncActionDialog
+        action={() => {return  Promise.resolve(); }}
+        onClose={(success: boolean) => null}
+        confirmButtonText={'test'}
+        successText={'test'}
+        failText={'test'}
+      />
+    const { container, getByText } = render(asyncActionDialog, { container: document.body });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/dialogs/async-action-dialog.tsx b/web-console/src/dialogs/async-action-dialog/async-action-dialog.tsx
similarity index 98%
rename from web-console/src/dialogs/async-action-dialog.tsx
rename to web-console/src/dialogs/async-action-dialog/async-action-dialog.tsx
index 1cfe144..9a00ff5 100644
--- a/web-console/src/dialogs/async-action-dialog.tsx
+++ b/web-console/src/dialogs/async-action-dialog/async-action-dialog.tsx
@@ -28,7 +28,7 @@ import { IconName } from '@blueprintjs/icons';
 import classNames from 'classnames';
 import * as React from 'react';
 
-import { AppToaster } from '../singletons/toaster';
+import { AppToaster } from '../../singletons/toaster';
 
 export interface AsyncAlertDialogProps extends React.Props<any> {
   action: null | (() => Promise<void>);
diff --git a/web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap b/web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap
new file mode 100644
index 0000000..0559735
--- /dev/null
+++ b/web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap
@@ -0,0 +1,731 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe compaction dialog compaction dialog snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog compaction-dialog"
+      >
+        <div
+          class="bp3-dialog-header"
+        >
+          <h4
+            class="bp3-heading"
+          >
+            Compaction config: test
+          </h4>
+          <button
+            aria-label="Close"
+            class="bp3-button bp3-minimal bp3-dialog-close-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-small-cross"
+              icon="small-cross"
+            >
+              <svg
+                data-icon="small-cross"
+                height="20"
+                viewBox="0 0 20 20"
+                width="20"
+              >
+                <desc>
+                  small-cross
+                </desc>
+                <path
+                  d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L11.41 10z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+        <div
+          class="auto-form"
+        >
+          <div
+            class="bp3-form-group"
+          >
+            <label
+              class="bp3-label"
+            >
+              Input segment size bytes
+               
+              <span
+                class="bp3-text-muted"
+              />
+            </label>
+            <div
+              class="bp3-form-content"
+            >
+              <div
+                class="bp3-control-group bp3-fill bp3-numeric-input"
+              >
+                <div
+                  class="bp3-input-group"
+                >
+                  <input
+                    autocomplete="off"
+                    class="bp3-input"
+                    min="0"
+                    style="padding-right: 10px;"
+                    type="text"
+                    value=""
+                  />
+                </div>
+                <div
+                  class="bp3-button-group bp3-vertical bp3-fixed"
+                >
+                  <button
+                    class="bp3-button"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-icon bp3-icon-chevron-up"
+                      icon="chevron-up"
+                    >
+                      <svg
+                        data-icon="chevron-up"
+                        height="16"
+                        viewBox="0 0 16 16"
+                        width="16"
+                      >
+                        <desc>
+                          chevron-up
+                        </desc>
+                        <path
+                          d="M12.71 9.29l-4-4C8.53 5.11 8.28 5 8 5s-.53.11-.71.29l-4 4a1.003 1.003 0 0 0 1.42 1.42L8 7.41l3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71z"
+                          fill-rule="evenodd"
+                        />
+                      </svg>
+                    </span>
+                  </button>
+                  <button
+                    class="bp3-button"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-icon bp3-icon-chevron-down"
+                      icon="chevron-down"
+                    >
+                      <svg
+                        data-icon="chevron-down"
+                        height="16"
+                        viewBox="0 0 16 16"
+                        width="16"
+                      >
+                        <desc>
+                          chevron-down
+                        </desc>
+                        <path
+                          d="M12 5c-.28 0-.53.11-.71.29L8 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42l4 4c.18.18.43.29.71.29s.53-.11.71-.29l4-4A1.003 1.003 0 0 0 12 5z"
+                          fill-rule="evenodd"
+                        />
+                      </svg>
+                    </span>
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div
+            class="bp3-form-group"
+          >
+            <label
+              class="bp3-label"
+            >
+              Keep segment granularity
+               
+              <span
+                class="bp3-text-muted"
+              />
+            </label>
+            <div
+              class="bp3-form-content"
+            >
+              <div
+                class="bp3-html-select"
+              >
+                <select>
+                  <option
+                    value="True"
+                  >
+                    True
+                  </option>
+                  <option
+                    value="False"
+                  >
+                    False
+                  </option>
+                </select>
+                <span
+                  class="bp3-icon bp3-icon-double-caret-vertical"
+                  icon="double-caret-vertical"
+                >
+                  <svg
+                    data-icon="double-caret-vertical"
+                    height="16"
+                    viewBox="0 0 16 16"
+                    width="16"
+                  >
+                    <desc>
+                      double-caret-vertical
+                    </desc>
+                    <path
+                      d="M5 7h6a1.003 1.003 0 0 0 .71-1.71l-3-3C8.53 2.11 8.28 2 8 2s-.53.11-.71.29l-3 3A1.003 1.003 0 0 0 5 7zm6 2H5a1.003 1.003 0 0 0-.71 1.71l3 3c.18.18.43.29.71.29s.53-.11.71-.29l3-3A1.003 1.003 0 0 0 11 9z"
+                      fill-rule="evenodd"
+                    />
+                  </svg>
+                </span>
+              </div>
+            </div>
+          </div>
+          <div
+            class="bp3-form-group"
+          >
+            <label
+              class="bp3-label"
+            >
+              Max num segments to compact
+               
+              <span
+                class="bp3-text-muted"
+              />
+            </label>
+            <div
+              class="bp3-form-content"
+            >
+              <div
+                class="bp3-control-group bp3-fill bp3-numeric-input"
+              >
+                <div
+                  class="bp3-input-group"
+                >
+                  <input
+                    autocomplete="off"
+                    class="bp3-input"
+                    min="0"
+                    style="padding-right: 10px;"
+                    type="text"
+                    value=""
+                  />
+                </div>
+                <div
+                  class="bp3-button-group bp3-vertical bp3-fixed"
+                >
+                  <button
+                    class="bp3-button"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-icon bp3-icon-chevron-up"
+                      icon="chevron-up"
+                    >
+                      <svg
+                        data-icon="chevron-up"
+                        height="16"
+                        viewBox="0 0 16 16"
+                        width="16"
+                      >
+                        <desc>
+                          chevron-up
+                        </desc>
+                        <path
+                          d="M12.71 9.29l-4-4C8.53 5.11 8.28 5 8 5s-.53.11-.71.29l-4 4a1.003 1.003 0 0 0 1.42 1.42L8 7.41l3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71z"
+                          fill-rule="evenodd"
+                        />
+                      </svg>
+                    </span>
+                  </button>
+                  <button
+                    class="bp3-button"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-icon bp3-icon-chevron-down"
+                      icon="chevron-down"
+                    >
+                      <svg
+                        data-icon="chevron-down"
+                        height="16"
+                        viewBox="0 0 16 16"
+                        width="16"
+                      >
+                        <desc>
+                          chevron-down
+                        </desc>
+                        <path
+                          d="M12 5c-.28 0-.53.11-.71.29L8 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42l4 4c.18.18.43.29.71.29s.53-.11.71-.29l4-4A1.003 1.003 0 0 0 12 5z"
+                          fill-rule="evenodd"
+                        />
+                      </svg>
+                    </span>
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div
+            class="bp3-form-group"
+          >
+            <label
+              class="bp3-label"
+            >
+              Skip offset from latest
+               
+              <span
+                class="bp3-text-muted"
+              />
+            </label>
+            <div
+              class="bp3-form-content"
+            >
+              <div
+                class="bp3-input-group"
+              >
+                <input
+                  class="bp3-input"
+                  style="padding-right: 10px;"
+                  type="text"
+                  value=""
+                />
+              </div>
+            </div>
+          </div>
+          <div
+            class="bp3-form-group"
+          >
+            <label
+              class="bp3-label"
+            >
+              Target compaction size bytes
+               
+              <span
+                class="bp3-text-muted"
+              />
+            </label>
+            <div
+              class="bp3-form-content"
+            >
+              <div
+                class="bp3-control-group bp3-fill bp3-numeric-input"
+              >
+                <div
+                  class="bp3-input-group"
+                >
+                  <input
+                    autocomplete="off"
+                    class="bp3-input"
+                    min="0"
+                    style="padding-right: 10px;"
+                    type="text"
+                    value=""
+                  />
+                </div>
+                <div
+                  class="bp3-button-group bp3-vertical bp3-fixed"
+                >
+                  <button
+                    class="bp3-button"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-icon bp3-icon-chevron-up"
+                      icon="chevron-up"
+                    >
+                      <svg
+                        data-icon="chevron-up"
+                        height="16"
+                        viewBox="0 0 16 16"
+                        width="16"
+                      >
+                        <desc>
+                          chevron-up
+                        </desc>
+                        <path
+                          d="M12.71 9.29l-4-4C8.53 5.11 8.28 5 8 5s-.53.11-.71.29l-4 4a1.003 1.003 0 0 0 1.42 1.42L8 7.41l3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71z"
+                          fill-rule="evenodd"
+                        />
+                      </svg>
+                    </span>
+                  </button>
+                  <button
+                    class="bp3-button"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-icon bp3-icon-chevron-down"
+                      icon="chevron-down"
+                    >
+                      <svg
+                        data-icon="chevron-down"
+                        height="16"
+                        viewBox="0 0 16 16"
+                        width="16"
+                      >
+                        <desc>
+                          chevron-down
+                        </desc>
+                        <path
+                          d="M12 5c-.28 0-.53.11-.71.29L8 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42l4 4c.18.18.43.29.71.29s.53-.11.71-.29l4-4A1.003 1.003 0 0 0 12 5z"
+                          fill-rule="evenodd"
+                        />
+                      </svg>
+                    </span>
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div
+            class="bp3-form-group"
+          >
+            <label
+              class="bp3-label"
+            >
+              Task context
+               
+              <span
+                class="bp3-text-muted"
+              />
+            </label>
+            <div
+              class="bp3-form-content"
+            >
+              <div
+                class=" ace_editor ace-tm"
+                id="ace-editor"
+                style="width: 100%; height: 8vh;"
+              >
+                <textarea
+                  autocapitalize="off"
+                  autocorrect="off"
+                  class="ace_text-input"
+                  spellcheck="false"
+                  style="opacity: 0;"
+                  wrap="off"
+                />
+                <div
+                  aria-hidden="true"
+                  class="ace_gutter"
+                  style="display: none;"
+                >
+                  <div
+                    class="ace_layer ace_gutter-layer ace_folding-enabled"
+                  />
+                  <div
+                    class="ace_gutter-active-line"
+                  />
+                </div>
+                <div
+                  class="ace_scroller"
+                >
+                  <div
+                    class="ace_content"
+                  >
+                    <div
+                      class="ace_layer ace_print-margin-layer"
+                    >
+                      <div
+                        class="ace_print-margin"
+                        style="left: 4px; visibility: hidden;"
+                      />
+                    </div>
+                    <div
+                      class="ace_layer ace_marker-layer"
+                    />
+                    <div
+                      class="ace_layer ace_text-layer"
+                      style="padding: 0px 4px;"
+                    />
+                    <div
+                      class="ace_layer ace_marker-layer"
+                    />
+                    <div
+                      class="ace_layer ace_cursor-layer ace_hidden-cursors"
+                    >
+                      <div
+                        class="ace_cursor"
+                      />
+                    </div>
+                  </div>
+                </div>
+                <div
+                  class="ace_scrollbar ace_scrollbar-v"
+                  style="display: none; width: 20px;"
+                >
+                  <div
+                    class="ace_scrollbar-inner"
+                    style="width: 20px;"
+                  />
+                </div>
+                <div
+                  class="ace_scrollbar ace_scrollbar-h"
+                  style="display: none; height: 20px;"
+                >
+                  <div
+                    class="ace_scrollbar-inner"
+                    style="height: 20px;"
+                  />
+                </div>
+                <div
+                  style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
+                >
+                  <div
+                    style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+                  />
+                  <div
+                    style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+                  >
+                    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div
+            class="bp3-form-group"
+          >
+            <label
+              class="bp3-label"
+            >
+              Task priority
+               
+              <span
+                class="bp3-text-muted"
+              />
+            </label>
+            <div
+              class="bp3-form-content"
+            >
+              <div
+                class="bp3-control-group bp3-fill bp3-numeric-input"
+              >
+                <div
+                  class="bp3-input-group"
+                >
+                  <input
+                    autocomplete="off"
+                    class="bp3-input"
+                    min="0"
+                    style="padding-right: 10px;"
+                    type="text"
+                    value=""
+                  />
+                </div>
+                <div
+                  class="bp3-button-group bp3-vertical bp3-fixed"
+                >
+                  <button
+                    class="bp3-button"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-icon bp3-icon-chevron-up"
+                      icon="chevron-up"
+                    >
+                      <svg
+                        data-icon="chevron-up"
+                        height="16"
+                        viewBox="0 0 16 16"
+                        width="16"
+                      >
+                        <desc>
+                          chevron-up
+                        </desc>
+                        <path
+                          d="M12.71 9.29l-4-4C8.53 5.11 8.28 5 8 5s-.53.11-.71.29l-4 4a1.003 1.003 0 0 0 1.42 1.42L8 7.41l3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71z"
+                          fill-rule="evenodd"
+                        />
+                      </svg>
+                    </span>
+                  </button>
+                  <button
+                    class="bp3-button"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-icon bp3-icon-chevron-down"
+                      icon="chevron-down"
+                    >
+                      <svg
+                        data-icon="chevron-down"
+                        height="16"
+                        viewBox="0 0 16 16"
+                        width="16"
+                      >
+                        <desc>
+                          chevron-down
+                        </desc>
+                        <path
+                          d="M12 5c-.28 0-.53.11-.71.29L8 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42l4 4c.18.18.43.29.71.29s.53-.11.71-.29l4-4A1.003 1.003 0 0 0 12 5z"
+                          fill-rule="evenodd"
+                        />
+                      </svg>
+                    </span>
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div
+            class="bp3-form-group"
+          >
+            <label
+              class="bp3-label"
+            >
+              Tuning config
+               
+              <span
+                class="bp3-text-muted"
+              />
+            </label>
+            <div
+              class="bp3-form-content"
+            >
+              <div
+                class=" ace_editor ace-tm"
+                id="ace-editor"
+                style="width: 100%; height: 8vh;"
+              >
+                <textarea
+                  autocapitalize="off"
+                  autocorrect="off"
+                  class="ace_text-input"
+                  spellcheck="false"
+                  style="opacity: 0;"
+                  wrap="off"
+                />
+                <div
+                  aria-hidden="true"
+                  class="ace_gutter"
+                  style="display: none;"
+                >
+                  <div
+                    class="ace_layer ace_gutter-layer ace_folding-enabled"
+                  />
+                  <div
+                    class="ace_gutter-active-line"
+                  />
+                </div>
+                <div
+                  class="ace_scroller"
+                >
+                  <div
+                    class="ace_content"
+                  >
+                    <div
+                      class="ace_layer ace_print-margin-layer"
+                    >
+                      <div
+                        class="ace_print-margin"
+                        style="left: 4px; visibility: hidden;"
+                      />
+                    </div>
+                    <div
+                      class="ace_layer ace_marker-layer"
+                    />
+                    <div
+                      class="ace_layer ace_text-layer"
+                      style="padding: 0px 4px;"
+                    />
+                    <div
+                      class="ace_layer ace_marker-layer"
+                    />
+                    <div
+                      class="ace_layer ace_cursor-layer ace_hidden-cursors"
+                    >
+                      <div
+                        class="ace_cursor"
+                      />
+                    </div>
+                  </div>
+                </div>
+                <div
+                  class="ace_scrollbar ace_scrollbar-v"
+                  style="display: none; width: 20px;"
+                >
+                  <div
+                    class="ace_scrollbar-inner"
+                    style="width: 20px;"
+                  />
+                </div>
+                <div
+                  class="ace_scrollbar ace_scrollbar-h"
+                  style="display: none; height: 20px;"
+                >
+                  <div
+                    class="ace_scrollbar-inner"
+                    style="height: 20px;"
+                  />
+                </div>
+                <div
+                  style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
+                >
+                  <div
+                    style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+                  />
+                  <div
+                    style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+                  >
+                    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-dialog-footer"
+        >
+          <div
+            class="bp3-dialog-footer-actions"
+          >
+            <button
+              class="bp3-button bp3-intent-danger"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Delete
+              </span>
+            </button>
+            <button
+              class="bp3-button"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Close
+              </span>
+            </button>
+            <button
+              class="bp3-button bp3-intent-primary"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Submit
+              </span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/dialogs/compaction-dialog.scss b/web-console/src/dialogs/compaction-dialog/compaction-dialog.scss
similarity index 100%
rename from web-console/src/dialogs/compaction-dialog.scss
rename to web-console/src/dialogs/compaction-dialog/compaction-dialog.scss
diff --git a/web-console/src/components/view-control-bar.tsx b/web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx
similarity index 59%
copy from web-console/src/components/view-control-bar.tsx
copy to web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx
index 679c671..c5d23f2 100644
--- a/web-console/src/components/view-control-bar.tsx
+++ b/web-console/src/dialogs/compaction-dialog/compaction-dialog.spec.tsx
@@ -16,25 +16,24 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
-
-import './view-control-bar.scss';
 
-export interface ViewControlBarProps {
-  label: string;
-}
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export class ViewControlBar extends React.Component<ViewControlBarProps, {}> {
-  constructor(props: ViewControlBarProps) {
-    super(props);
-  }
+import {CompactionDialog} from './compaction-dialog';
 
-  render() {
-    const { label, children } = this.props;
 
-    return <div className="view-control-bar">
-      <div className="control-label">{label}</div>
-      {children}
-    </div>;
-  }
-}
+describe('describe compaction dialog', () => {
+  it('compaction dialog snapshot', () => {
+    const compactionDialog =
+      <CompactionDialog
+        onClose={() => null}
+        onSave={(config: any) => null}
+        onDelete={() => null}
+        datasource={'test'}
+        configData={'test'}
+      />;
+    const { container, getByText } = render(compactionDialog, { container: document.body });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/dialogs/compaction-dialog.tsx b/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
similarity index 98%
rename from web-console/src/dialogs/compaction-dialog.tsx
rename to web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
index 87c2231..6129cc7 100644
--- a/web-console/src/dialogs/compaction-dialog.tsx
+++ b/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
@@ -19,7 +19,7 @@
 import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
 import * as React from 'react';
 
-import { AutoForm } from '../components/auto-form';
+import { AutoForm } from '../../components/auto-form/auto-form';
 
 import './compaction-dialog.scss';
 
diff --git a/web-console/src/dialogs/coordinator-dynamic-config/__snapshots__/coordinator-dynamic-config.spec.tsx.snap b/web-console/src/dialogs/coordinator-dynamic-config/__snapshots__/coordinator-dynamic-config.spec.tsx.snap
new file mode 100644
index 0000000..2d9d6e5
--- /dev/null
+++ b/web-console/src/dialogs/coordinator-dynamic-config/__snapshots__/coordinator-dynamic-config.spec.tsx.snap
@@ -0,0 +1,123 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe coordinator dynamic config coordinator dynamic config snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog snitch-dialog coordinator-dynamic-config"
+      >
+        <div
+          class="bp3-dialog-header"
+        >
+          <h4
+            class="bp3-heading"
+          >
+            Coordinator dynamic config
+          </h4>
+          <button
+            aria-label="Close"
+            class="bp3-button bp3-minimal bp3-dialog-close-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-small-cross"
+              icon="small-cross"
+            >
+              <svg
+                data-icon="small-cross"
+                height="20"
+                viewBox="0 0 20 20"
+                width="20"
+              >
+                <desc>
+                  small-cross
+                </desc>
+                <path
+                  d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L11.41 10z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+        <div
+          class="bp3-dialog-body"
+        >
+          <p>
+            Edit the coordinator dynamic configuration on the fly. For more information please refer to the 
+            <a
+              href="http://druid.io/docs/latest/configuration/index.html#dynamic-configuration"
+              target="_blank"
+            >
+              documentation
+            </a>
+            .
+          </p>
+          <div
+            class="auto-form"
+          />
+        </div>
+        <div
+          class="bp3-dialog-footer"
+        >
+          <div
+            class="bp3-dialog-footer-actions"
+          >
+            <button
+              class="bp3-button bp3-minimal left-align-button"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                History
+              </span>
+            </button>
+            <button
+              class="bp3-button bp3-intent-primary"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Next
+              </span>
+              <span
+                class="bp3-icon bp3-icon-arrow-right"
+                icon="arrow-right"
+              >
+                <svg
+                  data-icon="arrow-right"
+                  height="16"
+                  viewBox="0 0 16 16"
+                  width="16"
+                >
+                  <desc>
+                    arrow-right
+                  </desc>
+                  <path
+                    d="M14.7 7.29l-5-5a.965.965 0 0 0-.71-.3 1.003 1.003 0 0 0-.71 1.71l3.29 3.29H1.99c-.55 0-1 .45-1 1s.45 1 1 1h9.59l-3.29 3.29a1.003 1.003 0 0 0 1.42 1.42l5-5c.18-.18.29-.43.29-.71s-.12-.52-.3-.7z"
+                    fill-rule="evenodd"
+                  />
+                </svg>
+              </span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/dialogs/coordinator-dynamic-config.scss b/web-console/src/dialogs/coordinator-dynamic-config/coordinator-dynamic-config.scss
similarity index 100%
rename from web-console/src/dialogs/coordinator-dynamic-config.scss
rename to web-console/src/dialogs/coordinator-dynamic-config/coordinator-dynamic-config.scss
diff --git a/web-console/src/components/view-control-bar.tsx b/web-console/src/dialogs/coordinator-dynamic-config/coordinator-dynamic-config.spec.tsx
similarity index 62%
copy from web-console/src/components/view-control-bar.tsx
copy to web-console/src/dialogs/coordinator-dynamic-config/coordinator-dynamic-config.spec.tsx
index 679c671..a7e3dbc 100644
--- a/web-console/src/components/view-control-bar.tsx
+++ b/web-console/src/dialogs/coordinator-dynamic-config/coordinator-dynamic-config.spec.tsx
@@ -16,25 +16,20 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
-
-import './view-control-bar.scss';
 
-export interface ViewControlBarProps {
-  label: string;
-}
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export class ViewControlBar extends React.Component<ViewControlBarProps, {}> {
-  constructor(props: ViewControlBarProps) {
-    super(props);
-  }
+import {CoordinatorDynamicConfigDialog} from './coordinator-dynamic-config';
 
-  render() {
-    const { label, children } = this.props;
 
-    return <div className="view-control-bar">
-      <div className="control-label">{label}</div>
-      {children}
-    </div>;
-  }
-}
+describe('describe coordinator dynamic config', () => {
+  it('coordinator dynamic config snapshot', () => {
+    const coordinatorDynamicConfig =
+      <CoordinatorDynamicConfigDialog
+        onClose={() => null}
+      />;
+    const { container, getByText } = render(coordinatorDynamicConfig, { container: document.body });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/dialogs/coordinator-dynamic-config.tsx b/web-console/src/dialogs/coordinator-dynamic-config/coordinator-dynamic-config.tsx
similarity index 94%
rename from web-console/src/dialogs/coordinator-dynamic-config.tsx
rename to web-console/src/dialogs/coordinator-dynamic-config/coordinator-dynamic-config.tsx
index a5c0348..11c4369 100644
--- a/web-console/src/dialogs/coordinator-dynamic-config.tsx
+++ b/web-console/src/dialogs/coordinator-dynamic-config/coordinator-dynamic-config.tsx
@@ -21,12 +21,11 @@ import { IconNames } from '@blueprintjs/icons';
 import axios from 'axios';
 import * as React from 'react';
 
-import { AutoForm } from '../components/auto-form';
-import { ExternalLink } from '../components/external-link';
-import { AppToaster } from '../singletons/toaster';
-import { getDruidErrorMessage, QueryManager } from '../utils';
-
-import { SnitchDialog } from './snitch-dialog';
+import { AutoForm } from '../../components/auto-form/auto-form';
+import { ExternalLink } from '../../components/external-link/external-link';
+import { AppToaster } from '../../singletons/toaster';
+import { getDruidErrorMessage, QueryManager } from '../../utils';
+import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
 
 import './coordinator-dynamic-config.scss';
 
diff --git a/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap b/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap
new file mode 100644
index 0000000..522ff36
--- /dev/null
+++ b/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap
@@ -0,0 +1,132 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe history dialog history dialog snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog"
+      >
+        <div
+          class="history-record-container"
+        >
+          <span
+            class="history-dialog-title"
+          >
+            History
+          </span>
+          <div
+            class="history-record-entries"
+          >
+            <div
+              class="history-record-entry"
+            >
+              <div
+                class="bp3-card bp3-elevation-0"
+              >
+                <div
+                  class="history-record-title"
+                >
+                  <span
+                    class="history-record-title-change"
+                  >
+                    Change
+                  </span>
+                  <span />
+                </div>
+                <div
+                  class="bp3-divider"
+                />
+                <p />
+                <div
+                  class="json-collapse"
+                >
+                  <button
+                    class="bp3-button bp3-minimal"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-button-text"
+                    >
+                      Payload
+                    </span>
+                  </button>
+                  <div>
+                    <div
+                      class="bp3-collapse"
+                    >
+                      <div
+                        aria-hidden="false"
+                        class="bp3-collapse-body"
+                        style="transform: translateY(-0px);"
+                      />
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div
+              class="history-record-entry"
+            >
+              <div
+                class="bp3-card bp3-elevation-0"
+              >
+                <div
+                  class="history-record-title"
+                >
+                  <span
+                    class="history-record-title-change"
+                  >
+                    Change
+                  </span>
+                  <span />
+                </div>
+                <div
+                  class="bp3-divider"
+                />
+                <p />
+                <div
+                  class="json-collapse"
+                >
+                  <button
+                    class="bp3-button bp3-minimal"
+                    type="button"
+                  >
+                    <span
+                      class="bp3-button-text"
+                    >
+                      Payload
+                    </span>
+                  </button>
+                  <div>
+                    <div
+                      class="bp3-collapse"
+                    >
+                      <div
+                        aria-hidden="false"
+                        class="bp3-collapse-body"
+                        style="transform: translateY(-0px);"
+                      />
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/dialogs/history-dialog.scss b/web-console/src/dialogs/history-dialog/history-dialog.scss
similarity index 100%
rename from web-console/src/dialogs/history-dialog.scss
rename to web-console/src/dialogs/history-dialog/history-dialog.scss
diff --git a/web-console/src/components/view-control-bar.tsx b/web-console/src/dialogs/history-dialog/history-dialog.spec.tsx
similarity index 58%
copy from web-console/src/components/view-control-bar.tsx
copy to web-console/src/dialogs/history-dialog/history-dialog.spec.tsx
index 679c671..ccfa93c 100644
--- a/web-console/src/components/view-control-bar.tsx
+++ b/web-console/src/dialogs/history-dialog/history-dialog.spec.tsx
@@ -16,25 +16,21 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
-
-import './view-control-bar.scss';
 
-export interface ViewControlBarProps {
-  label: string;
-}
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export class ViewControlBar extends React.Component<ViewControlBarProps, {}> {
-  constructor(props: ViewControlBarProps) {
-    super(props);
-  }
+import {HistoryDialog} from './history-dialog';
 
-  render() {
-    const { label, children } = this.props;
 
-    return <div className="view-control-bar">
-      <div className="control-label">{label}</div>
-      {children}
-    </div>;
-  }
-}
+describe('describe history dialog', () => {
+  it('history dialog snapshot', () => {
+    const historyDialog =
+      <HistoryDialog
+        historyRecords={[{auditTime: 'test', auditInfo: 'test', payload: JSON.stringify({ name : 'test' })}, {auditTime: 'test', auditInfo: 'test',  payload: JSON.stringify({ name : 'test' })}]}
+        isOpen={true}
+      />;
+    const { container, getByText } = render(historyDialog, { container: document.body });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/dialogs/history-dialog.tsx b/web-console/src/dialogs/history-dialog/history-dialog.tsx
similarity index 97%
rename from web-console/src/dialogs/history-dialog.tsx
rename to web-console/src/dialogs/history-dialog/history-dialog.tsx
index 5704176..d781a15 100644
--- a/web-console/src/dialogs/history-dialog.tsx
+++ b/web-console/src/dialogs/history-dialog/history-dialog.tsx
@@ -19,7 +19,7 @@
 import {Card, Dialog, Divider, IDialogProps} from '@blueprintjs/core';
 import * as React from 'react';
 
-import { JSONCollapse } from '../components/json-collapse';
+import { JSONCollapse } from '../../components/json-collapse/json-collapse';
 
 import './history-dialog.scss';
 
diff --git a/web-console/src/components/clearable-input.tsx b/web-console/src/dialogs/index.ts
similarity index 50%
rename from web-console/src/components/clearable-input.tsx
rename to web-console/src/dialogs/index.ts
index da4df34..8a4ebe9 100644
--- a/web-console/src/components/clearable-input.tsx
+++ b/web-console/src/dialogs/index.ts
@@ -15,29 +15,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-import { Button, InputGroup } from '@blueprintjs/core';
-import { IconNames } from '@blueprintjs/icons';
-import classNames from 'classnames';
-import * as React from 'react';
-
-export interface ClearableInputProps extends React.Props<any> {
-  className?: string;
-  value: string;
-  onChange: (value: string) => void;
-  placeholder: string;
-}
-
-export class ClearableInput extends React.Component<ClearableInputProps, {}> {
-  render() {
-    const { className, value, onChange, placeholder } = this.props;
-
-    return <InputGroup
-      className={classNames('clearable-input', className)}
-      value={value}
-      onChange={(e: any) => onChange(e.target.value)}
-      rightElement={value ? <Button icon={IconNames.CROSS} minimal onClick={() => onChange('')} /> : undefined}
-      placeholder={placeholder}
-    />;
-  }
-}
+export * from './about-dialog/about-dialog';
+export * from './async-action-dialog/async-action-dialog';
+export * from './compaction-dialog/compaction-dialog';
+export * from './coordinator-dynamic-config/coordinator-dynamic-config';
+export * from './history-dialog/history-dialog';
+export * from './lookup-edit-dialog/lookup-edit-dialog';
+export * from './overlord-dynamic-config/overlord-dynamic-config';
+export * from './query-plan-dialog/query-plan-dialog';
+export * from './retention-dialog/retention-dialog';
+export * from './snitch-dialog/snitch-dialog';
+export * from './spec-dialog/spec-dialog';
+export * from './supervisor-table-action-dialog/supervisor-table-action-dialog';
+export * from './table-action-dialog/table-action-dialog';
+export * from './task-table-action-dialog/task-table-action-dialog';
diff --git a/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap b/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap
new file mode 100644
index 0000000..31deed8
--- /dev/null
+++ b/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap
@@ -0,0 +1,356 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe lookup edit dialog lookup edit dialog snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog lookup-edit-dialog"
+      >
+        <div
+          class="bp3-dialog-header"
+        >
+          <h4
+            class="bp3-heading"
+          >
+            Add lookup
+          </h4>
+          <button
+            aria-label="Close"
+            class="bp3-button bp3-minimal bp3-dialog-close-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-small-cross"
+              icon="small-cross"
+            >
+              <svg
+                data-icon="small-cross"
+                height="20"
+                viewBox="0 0 20 20"
+                width="20"
+              >
+                <desc>
+                  small-cross
+                </desc>
+                <path
+                  d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L11.41 10z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+        <div
+          class="bp3-form-group lookup-label"
+        >
+          <label
+            class="bp3-label"
+          >
+            Name: 
+             
+            <span
+              class="bp3-text-muted"
+            />
+          </label>
+          <div
+            class="bp3-form-content"
+          >
+            <div
+              class="bp3-input-group"
+            >
+              <input
+                class="bp3-input"
+                placeholder="Enter the lookup name"
+                style="padding-right: 10px;"
+                type="text"
+                value="test"
+              />
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-form-group lookup-label"
+        >
+          <label
+            class="bp3-label"
+          >
+            Tier:
+             
+            <span
+              class="bp3-text-muted"
+            />
+          </label>
+          <div
+            class="bp3-form-content"
+          >
+            <div
+              class="bp3-html-select"
+            >
+              <select>
+                <option
+                  value="a"
+                >
+                  a
+                </option>
+                <option
+                  value="b"
+                >
+                  b
+                </option>
+                <option
+                  value="c"
+                >
+                  c
+                </option>
+                <option
+                  value="d"
+                >
+                  d
+                </option>
+                <option
+                  value="e"
+                >
+                  e
+                </option>
+                <option
+                  value="f"
+                >
+                  f
+                </option>
+                <option
+                  value="g"
+                >
+                  g
+                </option>
+                <option
+                  value="h"
+                >
+                  h
+                </option>
+                <option
+                  value="i"
+                >
+                  i
+                </option>
+                <option
+                  value="j"
+                >
+                  j
+                </option>
+              </select>
+              <span
+                class="bp3-icon bp3-icon-double-caret-vertical"
+                icon="double-caret-vertical"
+              >
+                <svg
+                  data-icon="double-caret-vertical"
+                  height="16"
+                  viewBox="0 0 16 16"
+                  width="16"
+                >
+                  <desc>
+                    double-caret-vertical
+                  </desc>
+                  <path
+                    d="M5 7h6a1.003 1.003 0 0 0 .71-1.71l-3-3C8.53 2.11 8.28 2 8 2s-.53.11-.71.29l-3 3A1.003 1.003 0 0 0 5 7zm6 2H5a1.003 1.003 0 0 0-.71 1.71l3 3c.18.18.43.29.71.29s.53-.11.71-.29l3-3A1.003 1.003 0 0 0 11 9z"
+                    fill-rule="evenodd"
+                  />
+                </svg>
+              </span>
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-form-group lookup-label"
+        >
+          <label
+            class="bp3-label"
+          >
+            Version:
+             
+            <span
+              class="bp3-text-muted"
+            />
+          </label>
+          <div
+            class="bp3-form-content"
+          >
+            <div
+              class="bp3-input-group"
+            >
+              <input
+                class="bp3-input"
+                placeholder="Enter the lookup version"
+                style="padding-right: 0px;"
+                type="text"
+                value="test"
+              />
+              <span
+                class="bp3-input-action"
+              >
+                <button
+                  class="bp3-button bp3-minimal"
+                  type="button"
+                >
+                  <span
+                    class="bp3-button-text"
+                  >
+                    Use ISO as version
+                  </span>
+                </button>
+              </span>
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-form-group lookup-label"
+        >
+          <label
+            class="bp3-label"
+          >
+            Spec:
+             
+            <span
+              class="bp3-text-muted"
+            />
+          </label>
+          <div
+            class="bp3-form-content"
+          />
+        </div>
+        <div
+          class=" ace_editor ace-tm lookup-edit-dialog-textarea"
+          id="brace-editor"
+          style="width: auto; height: 40vh;"
+        >
+          <textarea
+            autocapitalize="off"
+            autocorrect="off"
+            class="ace_text-input"
+            spellcheck="false"
+            style="opacity: 0;"
+            wrap="off"
+          />
+          <div
+            aria-hidden="true"
+            class="ace_gutter"
+            style="display: none;"
+          >
+            <div
+              class="ace_layer ace_gutter-layer ace_folding-enabled"
+            />
+            <div
+              class="ace_gutter-active-line"
+            />
+          </div>
+          <div
+            class="ace_scroller"
+          >
+            <div
+              class="ace_content"
+            >
+              <div
+                class="ace_layer ace_print-margin-layer"
+              >
+                <div
+                  class="ace_print-margin"
+                  style="left: 4px; visibility: hidden;"
+                />
+              </div>
+              <div
+                class="ace_layer ace_marker-layer"
+              />
+              <div
+                class="ace_layer ace_text-layer"
+                style="padding: 0px 4px;"
+              />
+              <div
+                class="ace_layer ace_marker-layer"
+              />
+              <div
+                class="ace_layer ace_cursor-layer ace_hidden-cursors"
+              >
+                <div
+                  class="ace_cursor"
+                />
+              </div>
+            </div>
+          </div>
+          <div
+            class="ace_scrollbar ace_scrollbar-v"
+            style="display: none; width: 20px;"
+          >
+            <div
+              class="ace_scrollbar-inner"
+              style="width: 20px;"
+            />
+          </div>
+          <div
+            class="ace_scrollbar ace_scrollbar-h"
+            style="display: none; height: 20px;"
+          >
+            <div
+              class="ace_scrollbar-inner"
+              style="height: 20px;"
+            />
+          </div>
+          <div
+            style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
+          >
+            <div
+              style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+            />
+            <div
+              style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+            >
+              XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-dialog-footer"
+        >
+          <div
+            class="bp3-dialog-footer-actions"
+          >
+            <button
+              class="bp3-button"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Close
+              </span>
+            </button>
+            <button
+              class="bp3-button bp3-disabled bp3-intent-primary"
+              disabled=""
+              tabindex="-1"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Submit
+              </span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/dialogs/lookup-edit-dialog.scss b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss
similarity index 100%
rename from web-console/src/dialogs/lookup-edit-dialog.scss
rename to web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss
diff --git a/web-console/src/components/null-table-cell.tsx b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
similarity index 53%
rename from web-console/src/components/null-table-cell.tsx
rename to web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
index 01eeb7d..cfec37b 100644
--- a/web-console/src/components/null-table-cell.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
@@ -16,29 +16,29 @@
  * limitations under the License.
  */
 
+
 import * as React from 'react';
+import { render } from 'react-testing-library';
 
-import './null-table-cell.scss';
+import {LookupEditDialog} from './lookup-edit-dialog';
 
-export interface NullTableCellProps extends React.Props<any> {
-  value?: any;
-  timestamp?: boolean;
-  unparseable?: boolean;
-}
 
-export class NullTableCell extends React.Component<NullTableCellProps, {}> {
-  render() {
-    const { value, timestamp, unparseable } = this.props;
-    if (unparseable) {
-      return <span className="null-table-cell unparseable">{`error`}</span>;
-    } else if (value !== '' && value != null) {
-      if (timestamp) {
-        return <span className="null-table-cell timestamp" title={value}>{new Date(value).toISOString()}</span>;
-      } else {
-        return value;
-      }
-    } else {
-      return <span className="null-table-cell null">null</span>;
-    }
-  }
-}
+describe('describe lookup edit dialog', () => {
+  it('lookup edit dialog snapshot', () => {
+    const lookupEditDialog =
+      <LookupEditDialog
+        isOpen={true}
+        onClose={() => null}
+        onSubmit={() => null}
+        onChange={() => null}
+        lookupName={'test'}
+        lookupTier={'test'}
+        lookupVersion={'test'}
+        lookupSpec={'test'}
+        isEdit={false}
+        allLookupTiers={['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']}
+      />
+    const { container, getByText } = render(lookupEditDialog, { container: document.body });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/dialogs/lookup-edit-dialog.tsx b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
similarity index 99%
rename from web-console/src/dialogs/lookup-edit-dialog.tsx
rename to web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
index 49390ee..10febfd 100644
--- a/web-console/src/dialogs/lookup-edit-dialog.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
@@ -20,7 +20,7 @@ import { Button, Classes, Dialog, FormGroup, HTMLSelect, InputGroup, Intent } fr
 import * as React from 'react';
 import AceEditor from 'react-ace';
 
-import { validJson } from '../utils';
+import { validJson } from '../../utils';
 
 import './lookup-edit-dialog.scss';
 
diff --git a/web-console/src/dialogs/overlord-dynamic-config/__snapshots__/overload-dynamic-config.spec.tsx.snap b/web-console/src/dialogs/overlord-dynamic-config/__snapshots__/overload-dynamic-config.spec.tsx.snap
new file mode 100644
index 0000000..4cc9739
--- /dev/null
+++ b/web-console/src/dialogs/overlord-dynamic-config/__snapshots__/overload-dynamic-config.spec.tsx.snap
@@ -0,0 +1,356 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe overload dynamic config overload dynamic config snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog lookup-edit-dialog"
+      >
+        <div
+          class="bp3-dialog-header"
+        >
+          <h4
+            class="bp3-heading"
+          >
+            Add lookup
+          </h4>
+          <button
+            aria-label="Close"
+            class="bp3-button bp3-minimal bp3-dialog-close-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-small-cross"
+              icon="small-cross"
+            >
+              <svg
+                data-icon="small-cross"
+                height="20"
+                viewBox="0 0 20 20"
+                width="20"
+              >
+                <desc>
+                  small-cross
+                </desc>
+                <path
+                  d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L11.41 10z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+        <div
+          class="bp3-form-group lookup-label"
+        >
+          <label
+            class="bp3-label"
+          >
+            Name: 
+             
+            <span
+              class="bp3-text-muted"
+            />
+          </label>
+          <div
+            class="bp3-form-content"
+          >
+            <div
+              class="bp3-input-group"
+            >
+              <input
+                class="bp3-input"
+                placeholder="Enter the lookup name"
+                style="padding-right: 10px;"
+                type="text"
+                value="test"
+              />
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-form-group lookup-label"
+        >
+          <label
+            class="bp3-label"
+          >
+            Tier:
+             
+            <span
+              class="bp3-text-muted"
+            />
+          </label>
+          <div
+            class="bp3-form-content"
+          >
+            <div
+              class="bp3-html-select"
+            >
+              <select>
+                <option
+                  value="a"
+                >
+                  a
+                </option>
+                <option
+                  value="b"
+                >
+                  b
+                </option>
+                <option
+                  value="c"
+                >
+                  c
+                </option>
+                <option
+                  value="d"
+                >
+                  d
+                </option>
+                <option
+                  value="e"
+                >
+                  e
+                </option>
+                <option
+                  value="f"
+                >
+                  f
+                </option>
+                <option
+                  value="g"
+                >
+                  g
+                </option>
+                <option
+                  value="h"
+                >
+                  h
+                </option>
+                <option
+                  value="i"
+                >
+                  i
+                </option>
+                <option
+                  value="j"
+                >
+                  j
+                </option>
+              </select>
+              <span
+                class="bp3-icon bp3-icon-double-caret-vertical"
+                icon="double-caret-vertical"
+              >
+                <svg
+                  data-icon="double-caret-vertical"
+                  height="16"
+                  viewBox="0 0 16 16"
+                  width="16"
+                >
+                  <desc>
+                    double-caret-vertical
+                  </desc>
+                  <path
+                    d="M5 7h6a1.003 1.003 0 0 0 .71-1.71l-3-3C8.53 2.11 8.28 2 8 2s-.53.11-.71.29l-3 3A1.003 1.003 0 0 0 5 7zm6 2H5a1.003 1.003 0 0 0-.71 1.71l3 3c.18.18.43.29.71.29s.53-.11.71-.29l3-3A1.003 1.003 0 0 0 11 9z"
+                    fill-rule="evenodd"
+                  />
+                </svg>
+              </span>
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-form-group lookup-label"
+        >
+          <label
+            class="bp3-label"
+          >
+            Version:
+             
+            <span
+              class="bp3-text-muted"
+            />
+          </label>
+          <div
+            class="bp3-form-content"
+          >
+            <div
+              class="bp3-input-group"
+            >
+              <input
+                class="bp3-input"
+                placeholder="Enter the lookup version"
+                style="padding-right: 0px;"
+                type="text"
+                value="test"
+              />
+              <span
+                class="bp3-input-action"
+              >
+                <button
+                  class="bp3-button bp3-minimal"
+                  type="button"
+                >
+                  <span
+                    class="bp3-button-text"
+                  >
+                    Use ISO as version
+                  </span>
+                </button>
+              </span>
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-form-group lookup-label"
+        >
+          <label
+            class="bp3-label"
+          >
+            Spec:
+             
+            <span
+              class="bp3-text-muted"
+            />
+          </label>
+          <div
+            class="bp3-form-content"
+          />
+        </div>
+        <div
+          class=" ace_editor ace-tm lookup-edit-dialog-textarea"
+          id="brace-editor"
+          style="width: auto; height: 40vh;"
+        >
+          <textarea
+            autocapitalize="off"
+            autocorrect="off"
+            class="ace_text-input"
+            spellcheck="false"
+            style="opacity: 0;"
+            wrap="off"
+          />
+          <div
+            aria-hidden="true"
+            class="ace_gutter"
+            style="display: none;"
+          >
+            <div
+              class="ace_layer ace_gutter-layer ace_folding-enabled"
+            />
+            <div
+              class="ace_gutter-active-line"
+            />
+          </div>
+          <div
+            class="ace_scroller"
+          >
+            <div
+              class="ace_content"
+            >
+              <div
+                class="ace_layer ace_print-margin-layer"
+              >
+                <div
+                  class="ace_print-margin"
+                  style="left: 4px; visibility: hidden;"
+                />
+              </div>
+              <div
+                class="ace_layer ace_marker-layer"
+              />
+              <div
+                class="ace_layer ace_text-layer"
+                style="padding: 0px 4px;"
+              />
+              <div
+                class="ace_layer ace_marker-layer"
+              />
+              <div
+                class="ace_layer ace_cursor-layer ace_hidden-cursors"
+              >
+                <div
+                  class="ace_cursor"
+                />
+              </div>
+            </div>
+          </div>
+          <div
+            class="ace_scrollbar ace_scrollbar-v"
+            style="display: none; width: 20px;"
+          >
+            <div
+              class="ace_scrollbar-inner"
+              style="width: 20px;"
+            />
+          </div>
+          <div
+            class="ace_scrollbar ace_scrollbar-h"
+            style="display: none; height: 20px;"
+          >
+            <div
+              class="ace_scrollbar-inner"
+              style="height: 20px;"
+            />
+          </div>
+          <div
+            style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
+          >
+            <div
+              style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+            />
+            <div
+              style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
+            >
+              XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-dialog-footer"
+        >
+          <div
+            class="bp3-dialog-footer-actions"
+          >
+            <button
+              class="bp3-button"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Close
+              </span>
+            </button>
+            <button
+              class="bp3-button bp3-disabled bp3-intent-primary"
+              disabled=""
+              tabindex="-1"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Submit
+              </span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/components/menu-checkbox.tsx b/web-console/src/dialogs/overlord-dynamic-config/overload-dynamic-config.spec.tsx
similarity index 53%
copy from web-console/src/components/menu-checkbox.tsx
copy to web-console/src/dialogs/overlord-dynamic-config/overload-dynamic-config.spec.tsx
index 21b438b..40cc149 100644
--- a/web-console/src/components/menu-checkbox.tsx
+++ b/web-console/src/dialogs/overlord-dynamic-config/overload-dynamic-config.spec.tsx
@@ -16,16 +16,28 @@
  * limitations under the License.
  */
 
-import { Checkbox, ICheckboxProps } from '@blueprintjs/core';
-import * as React from 'react';
 
-import './menu-checkbox.scss';
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export class MenuCheckbox extends React.Component<ICheckboxProps, {}> {
+import {LookupEditDialog} from '..';
 
-  render() {
-    return <li className="menu-checkbox">
-      <Checkbox {...this.props}/>
-    </li>;
-  }
-}
+describe('describe overload dynamic config', () => {
+  it('overload dynamic config snapshot', () => {
+    const lookupEditDialog =
+      <LookupEditDialog
+        isOpen={true}
+        onClose={() => null}
+        onSubmit={() => null}
+        onChange={() => null}
+        lookupName={'test'}
+        lookupTier={'test'}
+        lookupVersion={'test'}
+        lookupSpec={'test'}
+        isEdit={false}
+        allLookupTiers={['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']}
+      />;
+    const { container, getByText } = render(lookupEditDialog, { container: document.body });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/dialogs/overlord-dynamic-config.scss b/web-console/src/dialogs/overlord-dynamic-config/overlord-dynamic-config.scss
similarity index 100%
rename from web-console/src/dialogs/overlord-dynamic-config.scss
rename to web-console/src/dialogs/overlord-dynamic-config/overlord-dynamic-config.scss
diff --git a/web-console/src/dialogs/overlord-dynamic-config.tsx b/web-console/src/dialogs/overlord-dynamic-config/overlord-dynamic-config.tsx
similarity index 92%
rename from web-console/src/dialogs/overlord-dynamic-config.tsx
rename to web-console/src/dialogs/overlord-dynamic-config/overlord-dynamic-config.tsx
index d22cde0..1c5a4ac 100644
--- a/web-console/src/dialogs/overlord-dynamic-config.tsx
+++ b/web-console/src/dialogs/overlord-dynamic-config/overlord-dynamic-config.tsx
@@ -21,12 +21,11 @@ import { IconNames } from '@blueprintjs/icons';
 import axios from 'axios';
 import * as React from 'react';
 
-import { AutoForm } from '../components/auto-form';
-import { ExternalLink } from '../components/external-link';
-import { AppToaster } from '../singletons/toaster';
-import { getDruidErrorMessage, QueryManager } from '../utils';
-
-import { SnitchDialog } from './snitch-dialog';
+import { AutoForm } from '../../components/auto-form/auto-form';
+import { ExternalLink } from '../../components/external-link/external-link';
+import { AppToaster } from '../../singletons/toaster';
+import { getDruidErrorMessage, QueryManager } from '../../utils';
+import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
 
 import './overlord-dynamic-config.scss';
 
diff --git a/web-console/src/dialogs/query-plan-dialog/__snapshots__/query-plan-dialog.spec.tsx.snap b/web-console/src/dialogs/query-plan-dialog/__snapshots__/query-plan-dialog.spec.tsx.snap
new file mode 100644
index 0000000..977f5a0
--- /dev/null
+++ b/web-console/src/dialogs/query-plan-dialog/__snapshots__/query-plan-dialog.spec.tsx.snap
@@ -0,0 +1,84 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe query plan dialog query plan dialog snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog query-plan-dialog"
+      >
+        <div
+          class="bp3-dialog-header"
+        >
+          <h4
+            class="bp3-heading"
+          >
+            Query plan
+          </h4>
+          <button
+            aria-label="Close"
+            class="bp3-button bp3-minimal bp3-dialog-close-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-small-cross"
+              icon="small-cross"
+            >
+              <svg
+                data-icon="small-cross"
+                height="20"
+                viewBox="0 0 20 20"
+                width="20"
+              >
+                <desc>
+                  small-cross
+                </desc>
+                <path
+                  d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L11.41 10z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+        <div
+          class="bp3-dialog-body"
+        >
+          <div>
+            test
+          </div>
+        </div>
+        <div
+          class="bp3-dialog-footer"
+        >
+          <div
+            class="bp3-dialog-footer-actions"
+          >
+            <button
+              class="bp3-button"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Close
+              </span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/dialogs/query-plan-dialog.scss b/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.scss
similarity index 100%
rename from web-console/src/dialogs/query-plan-dialog.scss
rename to web-console/src/dialogs/query-plan-dialog/query-plan-dialog.scss
diff --git a/web-console/src/components/view-control-bar.tsx b/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.spec.tsx
similarity index 61%
copy from web-console/src/components/view-control-bar.tsx
copy to web-console/src/dialogs/query-plan-dialog/query-plan-dialog.spec.tsx
index 679c671..4b6e53c 100644
--- a/web-console/src/components/view-control-bar.tsx
+++ b/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.spec.tsx
@@ -16,25 +16,22 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
-
-import './view-control-bar.scss';
 
-export interface ViewControlBarProps {
-  label: string;
-}
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export class ViewControlBar extends React.Component<ViewControlBarProps, {}> {
-  constructor(props: ViewControlBarProps) {
-    super(props);
-  }
+import {QueryPlanDialog} from './query-plan-dialog';
 
-  render() {
-    const { label, children } = this.props;
 
-    return <div className="view-control-bar">
-      <div className="control-label">{label}</div>
-      {children}
-    </div>;
-  }
-}
+describe('describe query plan dialog', () => {
+  it('query plan dialog snapshot', () => {
+    const queryPlanDialog =
+      <QueryPlanDialog
+        explainResult={'test'}
+        explainError={{name: 'test', message: 'test'}}
+        onClose={() => null}
+      />;
+    const { container, getByText } = render(queryPlanDialog, { container: document.body });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/dialogs/query-plan-dialog.tsx b/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.tsx
similarity index 99%
rename from web-console/src/dialogs/query-plan-dialog.tsx
rename to web-console/src/dialogs/query-plan-dialog/query-plan-dialog.tsx
index b8c9030..57f9c70 100644
--- a/web-console/src/dialogs/query-plan-dialog.tsx
+++ b/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.tsx
@@ -19,7 +19,7 @@
 import { Button, Classes, Dialog, FormGroup, InputGroup, TextArea } from '@blueprintjs/core';
 import * as React from 'react';
 
-import { BasicQueryExplanation, SemiJoinQueryExplanation } from '../utils';
+import { BasicQueryExplanation, SemiJoinQueryExplanation } from '../../utils';
 
 import './query-plan-dialog.scss';
 
diff --git a/web-console/src/dialogs/retention-dialog/__snapshots__/retention-dialog.spec.tsx.snap b/web-console/src/dialogs/retention-dialog/__snapshots__/retention-dialog.spec.tsx.snap
new file mode 100644
index 0000000..e114e98
--- /dev/null
+++ b/web-console/src/dialogs/retention-dialog/__snapshots__/retention-dialog.spec.tsx.snap
@@ -0,0 +1,173 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe retention dialog retention dialog snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog snitch-dialog retention-dialog"
+      >
+        <div
+          class="bp3-dialog-header"
+        >
+          <h4
+            class="bp3-heading"
+          >
+            Edit retention rules: test
+          </h4>
+          <button
+            aria-label="Close"
+            class="bp3-button bp3-minimal bp3-dialog-close-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-small-cross"
+              icon="small-cross"
+            >
+              <svg
+                data-icon="small-cross"
+                height="20"
+                viewBox="0 0 20 20"
+                width="20"
+              >
+                <desc>
+                  small-cross
+                </desc>
+                <path
+                  d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L11.41 10z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+        <div
+          class="bp3-dialog-body"
+        >
+          <p>
+            Druid uses rules to determine what data should be retained in the cluster. The rules are evaluated in order from top to bottom. For more information please refer to the 
+            <a
+              href="http://druid.io/docs/latest/operations/rule-configuration.html"
+              target="_blank"
+            >
+              documentation
+            </a>
+            .
+          </p>
+          <div
+            class="bp3-form-group"
+          >
+            <div
+              class="bp3-form-content"
+            />
+          </div>
+          <div
+            class="bp3-form-group right"
+          >
+            <div
+              class="bp3-form-content"
+            >
+              <button
+                class="bp3-button"
+                type="button"
+              >
+                <span
+                  class="bp3-icon bp3-icon-plus"
+                  icon="plus"
+                >
+                  <svg
+                    data-icon="plus"
+                    height="16"
+                    viewBox="0 0 16 16"
+                    width="16"
+                  >
+                    <desc>
+                      plus
+                    </desc>
+                    <path
+                      d="M13 7H9V3c0-.55-.45-1-1-1s-1 .45-1 1v4H3c-.55 0-1 .45-1 1s.45 1 1 1h4v4c0 .55.45 1 1 1s1-.45 1-1V9h4c.55 0 1-.45 1-1s-.45-1-1-1z"
+                      fill-rule="evenodd"
+                    />
+                  </svg>
+                </span>
+                <span
+                  class="bp3-button-text"
+                >
+                  New rule
+                </span>
+              </button>
+            </div>
+          </div>
+        </div>
+        <div
+          class="bp3-dialog-footer"
+        >
+          <div
+            class="bp3-dialog-footer-actions"
+          >
+            <button
+              class="bp3-button bp3-minimal left-align-button"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                History
+              </span>
+            </button>
+            <button
+              class="bp3-button"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Reset
+              </span>
+            </button>
+            <button
+              class="bp3-button bp3-intent-primary"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Next
+              </span>
+              <span
+                class="bp3-icon bp3-icon-arrow-right"
+                icon="arrow-right"
+              >
+                <svg
+                  data-icon="arrow-right"
+                  height="16"
+                  viewBox="0 0 16 16"
+                  width="16"
+                >
+                  <desc>
+                    arrow-right
+                  </desc>
+                  <path
+                    d="M14.7 7.29l-5-5a.965.965 0 0 0-.71-.3 1.003 1.003 0 0 0-.71 1.71l3.29 3.29H1.99c-.55 0-1 .45-1 1s.45 1 1 1h9.59l-3.29 3.29a1.003 1.003 0 0 0 1.42 1.42l5-5c.18-.18.29-.43.29-.71s-.12-.52-.3-.7z"
+                    fill-rule="evenodd"
+                  />
+                </svg>
+              </span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/dialogs/retention-dialog.spec.ts b/web-console/src/dialogs/retention-dialog/retention-dialog.array.spec.ts
similarity index 100%
rename from web-console/src/dialogs/retention-dialog.spec.ts
rename to web-console/src/dialogs/retention-dialog/retention-dialog.array.spec.ts
diff --git a/web-console/src/dialogs/retention-dialog.scss b/web-console/src/dialogs/retention-dialog/retention-dialog.scss
similarity index 100%
rename from web-console/src/dialogs/retention-dialog.scss
rename to web-console/src/dialogs/retention-dialog/retention-dialog.scss
diff --git a/web-console/src/components/view-control-bar.tsx b/web-console/src/dialogs/retention-dialog/retention-dialog.spec.tsx
similarity index 58%
copy from web-console/src/components/view-control-bar.tsx
copy to web-console/src/dialogs/retention-dialog/retention-dialog.spec.tsx
index 679c671..9a2b9c6 100644
--- a/web-console/src/components/view-control-bar.tsx
+++ b/web-console/src/dialogs/retention-dialog/retention-dialog.spec.tsx
@@ -16,25 +16,25 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
-
-import './view-control-bar.scss';
 
-export interface ViewControlBarProps {
-  label: string;
-}
+import * as React from 'react';
+import { render } from 'react-testing-library';
 
-export class ViewControlBar extends React.Component<ViewControlBarProps, {}> {
-  constructor(props: ViewControlBarProps) {
-    super(props);
-  }
+import {RetentionDialog} from './retention-dialog';
 
-  render() {
-    const { label, children } = this.props;
 
-    return <div className="view-control-bar">
-      <div className="control-label">{label}</div>
-      {children}
-    </div>;
-  }
-}
+describe('describe retention dialog', () => {
+  it('retention dialog snapshot', () => {
+    const retentionDialog =
+      <RetentionDialog
+        datasource={'test'}
+        rules={[null]}
+        tiers={['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']}
+        onEditDefaults={() => null}
+        onCancel={() => null}
+        onSave={() => null}
+      />;
+    const { container, getByText } = render(retentionDialog, { container: document.body });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+});
diff --git a/web-console/src/dialogs/retention-dialog.tsx b/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
similarity index 96%
rename from web-console/src/dialogs/retention-dialog.tsx
rename to web-console/src/dialogs/retention-dialog/retention-dialog.tsx
index 0232d24..10f4f09 100644
--- a/web-console/src/dialogs/retention-dialog.tsx
+++ b/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
@@ -21,10 +21,9 @@ import { IconNames } from '@blueprintjs/icons';
 import axios from 'axios';
 import * as React from 'react';
 
-import { Rule, RuleEditor } from '../components/rule-editor';
-import { QueryManager } from '../utils';
-
-import { SnitchDialog } from './snitch-dialog';
+import { Rule, RuleEditor } from '../../components/rule-editor/rule-editor';
+import { QueryManager } from '../../utils';
+import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
 
 import './retention-dialog.scss';
 
diff --git a/web-console/src/dialogs/snitch-dialog/__snapshots__/snitch-dialog.spec.tsx.snap b/web-console/src/dialogs/snitch-dialog/__snapshots__/snitch-dialog.spec.tsx.snap
new file mode 100644
index 0000000..0c119c8
--- /dev/null
+++ b/web-console/src/dialogs/snitch-dialog/__snapshots__/snitch-dialog.spec.tsx.snap
@@ -0,0 +1,65 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`describe snitch dialog snitch dialog snapshot 1`] = `
+<div
+  class="bp3-portal"
+>
+  <div
+    class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+  >
+    <div
+      class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    />
+    <div
+      class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
+    >
+      <div
+        class="bp3-dialog snitch-dialog"
+      >
+        <div
+          class="bp3-dialog-body"
+        />
+        <div
+          class="bp3-dialog-footer"
+        >
+          <div
+            class="bp3-dialog-footer-actions"
+          >
+            <button
+              class="bp3-button bp3-intent-primary"
+              type="button"
+            >
+              <span
+                class="bp3-button-text"
+              >
+                Next
+              </span>
+              <span
+                class="bp3-icon bp3-icon-arrow-right"
+                icon="arrow-right"
+              >
+                <svg
+                  data-icon="arrow-right"
+                  height="16"
+                  viewBox="0 0 16 16"
+                  width="16"
+                >
+                  <desc>
+                    arrow-right
+                  </desc>
+                  <path
+                    d="M14.7 7.29l-5-5a.965.965 0 0 0-.71-.3 1.003 1.003 0 0 0-.71 1.71l3.29 3.29H1.99c-.55 0-1 .45-1 1s.45 1 1 1h9.59l-3.29 3.29a1.003 1.003 0 0 0 1.42 1.42l5-5c.18-.18.29-.43.29-.71s-.12-.52-.3-.7z"
+                    fill-rule="evenodd"
+                  />
+                </svg>
+              </span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/dialogs/snitch-dialog.scss b/web-console/src/dialogs/snitch-dialog/snitch-dialog.scss
similarity index 100%
rename from web-console/src/dialogs/snitch-dialog.scss
rename to web-console/src/dialogs/snitch-dialog/snitch-dialog.scss
diff --git a/web-console/src/components/external-link.tsx b/web-console/src/dialogs/snitch-dialog/snitch-dialog.spec.tsx
similarity index 66%
copy from web-console/src/components/external-link.tsx
copy to web-console/src/dialogs/snitch-dialog/snitch-dialog.spec.tsx
index 0a9c102..19fdc34 100644
--- a/web-console/src/components/external-link.tsx
+++ b/web-console/src/dialogs/snitch-dialog/snitch-dialog.spec.tsx
@@ -16,21 +16,20 @@
  * limitations under the License.
  */
 
-import * as React from 'react';
 
-export interface ExternalLinkProps extends React.Props<any> {
-  href: string;
-}
... 4525 lines suppressed ...


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org