+ {{! we only need to check for an empty name here as ember munges autofocus, once we have autofocus back revisit this}}
+
-{{# if (and item.ID (not-eq item.ID 'anonymous')) }}
+{{# if (and (not create) (not-eq item.ID 'anonymous')) }}
{{#confirmation-dialog message='Are you sure you want to delete this ACL token?'}}
{{#block-slot 'action' as |confirm|}}
diff --git a/ui-v2/app/templates/dc/kv/-form.hbs b/ui-v2/app/templates/dc/kv/-form.hbs
index a001faeaed..6303969045 100644
--- a/ui-v2/app/templates/dc/kv/-form.hbs
+++ b/ui-v2/app/templates/dc/kv/-form.hbs
@@ -11,21 +11,23 @@
around it in acls, remove or add for consistency }}
{{#if create }}
-
+ {{! we only need to check for an empty keyname here as ember munges autofocus, once we have autofocus back revisit this}}
+
{{ else }}
diff --git a/ui-v2/app/templates/dc/kv/index.hbs b/ui-v2/app/templates/dc/kv/index.hbs
index 20ce7c7479..6db169a64d 100644
--- a/ui-v2/app/templates/dc/kv/index.hbs
+++ b/ui-v2/app/templates/dc/kv/index.hbs
@@ -18,6 +18,13 @@
{{/if}}
{{/block-slot}}
+ {{#block-slot 'toolbar'}}
+{{#if (gt items.length 0) }}
+
+{{/if}}
+ {{/block-slot}}
{{#block-slot 'actions'}}
{{#if (not-eq parent.Key '/') }}
Create
@@ -26,9 +33,9 @@
{{/if}}
{{/block-slot}}
{{#block-slot 'content'}}
-{{#if (gt items.length 0)}}
+{{#if (gt filtered.length 0)}}
{{#tabular-collection
- items=(sort-by 'isFolder:desc' items) as |item index|
+ items=(sort-by 'isFolder:desc' 'Key:asc' filtered) as |item index|
}}
{{#block-slot 'header'}}
Name |
diff --git a/ui-v2/app/templates/dc/nodes/-healthchecks.hbs b/ui-v2/app/templates/dc/nodes/-healthchecks.hbs
index 772989797b..d199676133 100644
--- a/ui-v2/app/templates/dc/nodes/-healthchecks.hbs
+++ b/ui-v2/app/templates/dc/nodes/-healthchecks.hbs
@@ -1,6 +1,6 @@
-
+
{{#each (sort-by (action 'sortChecksByImportance') item.Checks) as |check| }}
- {{healthcheck-status tagName='li' name=check.Name class=check.Status status=check.Status notes=check.Notes output=check.Output}}
+ {{healthcheck-status data-test-node-healthcheck=check.Name tagName='li' name=check.Name class=check.Status status=check.Status notes=check.Notes output=check.Output}}
{{/each}}
diff --git a/ui-v2/app/templates/dc/nodes/-services.hbs b/ui-v2/app/templates/dc/nodes/-services.hbs
index d1efe5dc97..185875f3ce 100644
--- a/ui-v2/app/templates/dc/nodes/-services.hbs
+++ b/ui-v2/app/templates/dc/nodes/-services.hbs
@@ -1,10 +1,11 @@
{{#if (gt items.length 0) }}
{{/if}}
{{#if (gt filtered.length 0)}}
{{#tabular-collection
+ data-test-services
items=filtered as |item index|
}}
{{#block-slot 'header'}}
@@ -13,10 +14,10 @@
Tags |
{{/block-slot}}
{{#block-slot 'row'}}
-
+ |
{{item.Service}}
|
-
+ |
{{item.Port}}
|
diff --git a/ui-v2/app/templates/dc/nodes/show.hbs b/ui-v2/app/templates/dc/nodes/show.hbs
index 66764222c5..78586c65ee 100644
--- a/ui-v2/app/templates/dc/nodes/show.hbs
+++ b/ui-v2/app/templates/dc/nodes/show.hbs
@@ -45,7 +45,7 @@
)
) as |panel|
}}
- {{#tab-section id=panel.id selected=(eq (if selectedTab selectedTab 'health-checks') panel.id) onchange=(action (mut selectedTab) value="target.value")}}
+ {{#tab-section id=panel.id selected=(eq (if selectedTab selectedTab 'health-checks') panel.id) onchange=(action "change")}}
{{partial panel.partial}}
{{/tab-section}}
{{/each}}
diff --git a/ui-v2/app/utils/get-component-factory.js b/ui-v2/app/utils/get-component-factory.js
new file mode 100644
index 0000000000..5ebc174ca7
--- /dev/null
+++ b/ui-v2/app/utils/get-component-factory.js
@@ -0,0 +1,9 @@
+export default function(owner, key = '-view-registry:main') {
+ const components = owner.lookup(key);
+ return function(el) {
+ const id = el.getAttribute('id');
+ if (id) {
+ return components[id];
+ }
+ };
+}
diff --git a/ui-v2/app/utils/left-trim.js b/ui-v2/app/utils/left-trim.js
new file mode 100644
index 0000000000..279b3d02d5
--- /dev/null
+++ b/ui-v2/app/utils/left-trim.js
@@ -0,0 +1,3 @@
+export default function leftTrim(str = '', search = '') {
+ return str.indexOf(search) === 0 ? str.substr(search.length) : str;
+}
diff --git a/ui-v2/app/utils/qsa-factory.js b/ui-v2/app/utils/qsa-factory.js
new file mode 100644
index 0000000000..ff5770a349
--- /dev/null
+++ b/ui-v2/app/utils/qsa-factory.js
@@ -0,0 +1,5 @@
+export default function(doc = document) {
+ return function(sel, context = doc) {
+ return context.querySelectorAll(sel);
+ };
+}
diff --git a/ui-v2/app/utils/right-trim.js b/ui-v2/app/utils/right-trim.js
new file mode 100644
index 0000000000..5e1b1d3c46
--- /dev/null
+++ b/ui-v2/app/utils/right-trim.js
@@ -0,0 +1,4 @@
+export default function rightTrim(str = '', search = '') {
+ const pos = str.length - search.length;
+ return str.lastIndexOf(search) === pos ? str.substr(0, pos) : str;
+}
diff --git a/ui-v2/app/validations/acl.js b/ui-v2/app/validations/acl.js
index 8760894873..5878e768ee 100644
--- a/ui-v2/app/validations/acl.js
+++ b/ui-v2/app/validations/acl.js
@@ -2,5 +2,4 @@ import { validatePresence, validateLength } from 'ember-changeset-validations/va
export default {
Name: [validatePresence(true), validateLength({ min: 1 })],
Type: validatePresence(true),
- ID: validateLength({ min: 1 }),
};
diff --git a/ui-v2/ember-cli-build.js b/ui-v2/ember-cli-build.js
index 9a96a6772b..c51bd62665 100644
--- a/ui-v2/ember-cli-build.js
+++ b/ui-v2/ember-cli-build.js
@@ -1,7 +1,7 @@
'use strict';
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
-
+const stew = require('broccoli-stew');
module.exports = function(defaults) {
let app = new EmberApp(defaults, {
'ember-cli-babel': {
@@ -43,6 +43,9 @@ module.exports = function(defaults) {
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
-
- return app.toTree();
+ let tree = app.toTree();
+ if (app.env === 'production') {
+ tree = stew.rm(tree, 'consul-api-double');
+ }
+ return tree;
};
diff --git a/ui-v2/package.json b/ui-v2/package.json
index 10ad4b70fe..13642f549c 100644
--- a/ui-v2/package.json
+++ b/ui-v2/package.json
@@ -15,7 +15,9 @@
"format:js": "prettier --write \"{app,config,lib,server,tests}/**/*.js\" ./*.js ./.*.js",
"start": "ember serve",
"test": "ember test",
- "precommit": "lint-staged"
+ "test:view": "ember test --server",
+ "precommit": "lint-staged",
+ "postinstall": "rsync -aq ./node_modules/@hashicorp/consul-api-double/ ./public/consul-api-double/"
},
"lint-staged": {
"{app,config,lib,server,tests}/**/*.js": [
@@ -27,10 +29,14 @@
"git add"
]
},
+ "dependencies": {},
"devDependencies": {
+ "@hashicorp/consul-api-double": "^1.0.0",
+ "@hashicorp/ember-cli-api-double": "^1.0.2",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"base64-js": "^1.3.0",
"broccoli-asset-rev": "^2.4.5",
+ "broccoli-stew": "^1.5.0",
"ember-ajax": "^3.0.0",
"ember-block-slots": "^1.1.11",
"ember-browserify": "^1.2.2",
@@ -40,6 +46,7 @@
"ember-cli-app-version": "^3.0.0",
"ember-cli-autoprefixer": "^0.8.1",
"ember-cli-babel": "^6.6.0",
+ "ember-cli-cjs-transform": "^1.2.0",
"ember-cli-clipboard": "^0.9.0",
"ember-cli-code-coverage": "^1.0.0-beta.4",
"ember-cli-dependency-checker": "^2.0.0",
@@ -55,6 +62,7 @@
"ember-cli-shims": "^1.2.0",
"ember-cli-sri": "^2.1.0",
"ember-cli-uglify": "^2.0.0",
+ "ember-cli-yadda": "^0.4.0",
"ember-collection": "^1.0.0-alpha.7",
"ember-composable-helpers": "^2.1.0",
"ember-computed-style": "^0.2.0",
diff --git a/ui-v2/tests/acceptance/components/acl-filter.feature b/ui-v2/tests/acceptance/components/acl-filter.feature
new file mode 100644
index 0000000000..4502db4515
--- /dev/null
+++ b/ui-v2/tests/acceptance/components/acl-filter.feature
@@ -0,0 +1,35 @@
+@setupApplicationTest
+Feature: Acl Filter
+ Scenario: Filtering [Model]
+ Given 1 datacenter model with the value "dc-1"
+ And 2 [Model] models
+ When I visit the [Page] page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be [Url]
+
+ Then I see 2 [Model] models
+ And I see allIsSelected on the filter
+
+ When I click management on the filter
+ Then I see managementIsSelected on the filter
+ And I see 1 [Model] model
+
+ When I click client on the filter
+ Then I see clientIsSelected on the filter
+ And I see 1 [Model] model
+
+ When I click all on the filter
+ Then I see allIsSelected on the filter
+ Then I type with yaml
+ ---
+ s: Anonymous Token
+ ---
+ And I see 1 [Model] model with the name "Anonymous Token"
+
+ Where:
+ -------------------------------------------------
+ | Model | Page | Url |
+ | acl | acls | /dc-1/acls |
+ -------------------------------------------------
diff --git a/ui-v2/tests/acceptance/components/catalog-filter.feature b/ui-v2/tests/acceptance/components/catalog-filter.feature
new file mode 100644
index 0000000000..2635228002
--- /dev/null
+++ b/ui-v2/tests/acceptance/components/catalog-filter.feature
@@ -0,0 +1,88 @@
+@setupApplicationTest
+Feature: components / catalog-filter
+ Scenario: Filtering [Model]
+ Given 1 datacenter model with the value "dc-1"
+ And 3 service models from yaml
+ ---
+ - ChecksPassing: 1
+ ChecksWarning: 0
+ ChecksCritical: 0
+ - ChecksPassing: 0
+ ChecksWarning: 1
+ ChecksCritical: 0
+ - ChecksPassing: 0
+ ChecksWarning: 0
+ ChecksCritical: 1
+ ---
+ And 3 node models from yaml
+ ---
+ - Checks:
+ - Status: passing
+ - Checks:
+ - Status: warning
+ - Checks:
+ - Status: critical
+
+ ---
+ When I visit the [Page] page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be [Url]
+
+ Then I see 3 [Model] models
+ And I see allIsSelected on the filter
+
+ When I click passing on the filter
+ And I see passingIsSelected on the filter
+ And I see 1 [Model] model
+
+ When I click warning on the filter
+ And I see warningIsSelected on the filter
+ And I see 1 [Model] model
+
+ When I click critical on the filter
+ And I see criticalIsSelected on the filter
+ And I see 1 [Model] model
+
+ When I click all on the filter
+ And I see allIsSelected on the filter
+ Then I type with yaml
+ ---
+ s: [Model]-0
+ ---
+ And I see 1 [Model] model with the name "[Model]-0"
+
+ Where:
+ -------------------------------------------------
+ | Model | Page | Url |
+ | service | services | /dc-1/services |
+ | node | nodes | /dc-1/nodes |
+ -------------------------------------------------
+ Scenario: Filtering [Model] in [Page]
+ Given 1 datacenter model with the value "dc1"
+ And 2 node models from yaml
+ ---
+ - ID: node-0
+ ---
+ When I visit the node page for yaml
+ ---
+ dc: dc1
+ node: node-0
+ ---
+ # And I see 3 healthcheck model with the name "Disk Util"
+ # And then pause for 5000
+ When I click services on the tabs
+ And I see servicesIsSelected on the tabs
+
+ Then I type with yaml
+ ---
+ s: 65535
+ ---
+ And I see 1 [Model] model
+ And I see 1 [Model] model with the port "65535"
+ Where:
+ -------------------------------------------------
+ | Model | Page | Url |
+ | service | node | /dc-1/nodes/node-0 |
+ -------------------------------------------------
diff --git a/ui-v2/tests/acceptance/components/kv-filter.feature b/ui-v2/tests/acceptance/components/kv-filter.feature
new file mode 100644
index 0000000000..ebe740c466
--- /dev/null
+++ b/ui-v2/tests/acceptance/components/kv-filter.feature
@@ -0,0 +1,26 @@
+@setupApplicationTest
+Feature: components / kv-filter
+ Scenario: Filtering using the freetext filter
+ Given 1 datacenter model with the value "dc-1"
+ And 2 [Model] models from yaml
+ ---
+ - hi
+ - there
+ ---
+ When I visit the [Page] page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be [Url]
+ Then I type with yaml
+ ---
+ s: [Text]
+ ---
+ And I see 1 [Model] model with the name "[Text]"
+
+ Where:
+ ----------------------------------------------------------------
+ | Model | Page | Url | Text | Property |
+ | kv | kvs | /dc-1/kv | hi | name |
+ | kv | kvs | /dc-1/kv | there | name |
+ ----------------------------------------------------------------
diff --git a/ui-v2/tests/acceptance/dc/acls/delete.feature b/ui-v2/tests/acceptance/dc/acls/delete.feature
new file mode 100644
index 0000000000..9a59d1ec0b
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/acls/delete.feature
@@ -0,0 +1,17 @@
+@setupApplicationTest
+Feature: dc / acls / delete: ACL Delete
+ Scenario: Delete ACL
+ Given 1 datacenter model with the value "datacenter"
+ And 1 acl model from yaml
+ ---
+ Name: something
+ ID: key
+ ---
+ When I visit the acls page for yaml
+ ---
+ dc: datacenter
+ ---
+ And I click actions on the acls
+ And I click delete on the acls
+ And I click confirmDelete on the acls
+ Then a PUT request is made to "/v1/acl/destroy/key?dc=datacenter"
diff --git a/ui-v2/tests/acceptance/dc/acls/update.feature b/ui-v2/tests/acceptance/dc/acls/update.feature
new file mode 100644
index 0000000000..77c6417fd7
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/acls/update.feature
@@ -0,0 +1,39 @@
+@setupApplicationTest
+Feature: dc / acls / update: ACL Update
+ Scenario: Update to [Name], [Type], [Rules]
+ Given 1 datacenter model with the value "datacenter"
+ And 1 acl model from yaml
+ ---
+ ID: key
+ ---
+ When I visit the acl page for yaml
+ ---
+ dc: datacenter
+ acl: key
+ ---
+ Then the url should be /datacenter/acls/key
+ Then I type with yaml
+ ---
+ name: [Name]
+ ---
+ And I click "[value=[Type]]"
+ And I submit
+ Then a PUT request is made to "/v1/acl/update?dc=datacenter" with the body from yaml
+ ---
+ Name: [Name]
+ Type: [Type]
+ ---
+ Where:
+ ----------------------------------------------------------
+ | Name | Type | Rules |
+ | key-name | client | node "0" {policy = "read"} |
+ | key name | management | node "0" {policy = "write"} |
+ | key%20name | client | node "0" {policy = "read"} |
+ | utf8? | management | node "0" {policy = "write"} |
+ ----------------------------------------------------------
+@ignore
+ Scenario: Rules can be edited/updated
+ Then ok
+@ignore
+ Scenario: The feedback dialog says success or failure
+ Then ok
diff --git a/ui-v2/tests/acceptance/dc/index.feature b/ui-v2/tests/acceptance/dc/index.feature
new file mode 100644
index 0000000000..5a76bc22b3
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/index.feature
@@ -0,0 +1,8 @@
+@setupApplicationTest
+Feature: Datacenters
+@ignore
+ Scenario: Arriving at the service page
+ Given 10 datacenter models
+ When I visit the index page
+ And I click "[data-test-datacenter-selected]"
+ Then I see 10 datacenter models
diff --git a/ui-v2/tests/acceptance/dc/kvs/delete.feature b/ui-v2/tests/acceptance/dc/kvs/delete.feature
new file mode 100644
index 0000000000..324240b9c9
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/kvs/delete.feature
@@ -0,0 +1,16 @@
+@setupApplicationTest
+Feature: dc / kvs / delete: KV Delete
+ Scenario: Delete ACL
+ Given 1 datacenter model with the value "datacenter"
+ And 1 kv model from yaml
+ ---
+ - key-name
+ ---
+ When I visit the kvs page for yaml
+ ---
+ dc: datacenter
+ ---
+ And I click actions on the kvs
+ And I click delete on the kvs
+ And I click confirmDelete on the kvs
+ Then a DELETE request is made to "/v1/kv/key-name?dc=datacenter"
diff --git a/ui-v2/tests/acceptance/dc/kvs/list-order.feature b/ui-v2/tests/acceptance/dc/kvs/list-order.feature
new file mode 100644
index 0000000000..072f28ab27
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/kvs/list-order.feature
@@ -0,0 +1,56 @@
+@setupApplicationTest
+Feature: dc / kvs / list-order
+ In order to be able to find key values easier
+ As a user
+ I want to see the Key/Values listed alphabetically
+
+ Scenario: I have 19 folders
+ Given 1 datacenter model with the value "datacenter"
+ And 19 kv models from yaml
+ ---
+ - __secretzzz/
+ - a-thing-service/
+ - a-thing-y-again-service/
+ - a-thing-y-againzz-service/
+ - a-z-search-service/
+ - blood-pressure-service/
+ - callToAction-items/
+ - configuration/
+ - content-service/
+ - currentRepository-jobs/
+ - currentRepository-service/
+ - first-service/
+ - logs-service/
+ - rabmq-svc/
+ - rabmqUtilities/
+ - schedule-service/
+ - vanApp-service/
+ - vanCat-service/
+ - vanTaxi-service/
+ ---
+ When I visit the kvs page for yaml
+ ---
+ dc: datacenter
+ ---
+ Then I see name on the kvs like yaml
+ ---
+ - __secretzzz/
+ - a-thing-service/
+ - a-thing-y-again-service/
+ - a-thing-y-againzz-service/
+ - a-z-search-service/
+ - blood-pressure-service/
+ - callToAction-items/
+ - configuration/
+ - content-service/
+ - currentRepository-jobs/
+ - currentRepository-service/
+ - first-service/
+ - logs-service/
+ - rabmq-svc/
+ - rabmqUtilities/
+ - schedule-service/
+ - vanApp-service/
+ - vanCat-service/
+ - vanTaxi-service/
+ ---
diff --git a/ui-v2/tests/acceptance/dc/kvs/update.feature b/ui-v2/tests/acceptance/dc/kvs/update.feature
new file mode 100644
index 0000000000..b6a880c8dc
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/kvs/update.feature
@@ -0,0 +1,36 @@
+@setupApplicationTest
+Feature: dc / kvs / update: KV Update
+ Scenario: Update to [Name] change value to [Value]
+ Given 1 datacenter model with the value "datacenter"
+ And 1 kv model from yaml
+ ---
+ Key: [Name]
+ ---
+ When I visit the kv page for yaml
+ ---
+ dc: datacenter
+ kv: [Name]
+ ---
+ Then the url should be /datacenter/kv/[Name]/edit
+ Then I type with yaml
+ ---
+ value: [Value]
+ ---
+ And I submit
+ Then a PUT request is made to "/v1/kv/[Name]?dc=datacenter" with the body "[Value]"
+ Where:
+ --------------------------------------------
+ | Name | Value |
+ | key | value |
+ | key-name | a value |
+ | folder/key-name | a value |
+ --------------------------------------------
+@ignore
+ Scenario: The feedback dialog says success or failure
+ Then ok
+@ignore
+ Scenario: KV's with spaces are saved correctly
+ Then ok
+@ignore
+ Scenario: KV's with returns are saved correctly
+ Then ok
diff --git a/ui-v2/tests/acceptance/dc/list.feature b/ui-v2/tests/acceptance/dc/list.feature
new file mode 100644
index 0000000000..bd77f6c817
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/list.feature
@@ -0,0 +1,20 @@
+@setupApplicationTest
+Feature: List Models
+ Scenario: Listing [Model]
+ Given 1 datacenter model with the value "dc-1"
+ And 3 [Model] models
+ When I visit the [Page] page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be [Url]
+
+ Then I see 3 [Model] models
+ Where:
+ -------------------------------------------------
+ | Model | Page | Url |
+ | service | services | /dc-1/services |
+ | node | nodes | /dc-1/nodes |
+ | kv | kvs | /dc-1/kv |
+ | acl | acls | /dc-1/acls |
+ -------------------------------------------------
diff --git a/ui-v2/tests/acceptance/dc/nodes/index.feature b/ui-v2/tests/acceptance/dc/nodes/index.feature
new file mode 100644
index 0000000000..4e6c4d0637
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/nodes/index.feature
@@ -0,0 +1,11 @@
+@setupApplicationTest
+Feature: Nodes
+ Scenario:
+ Given 1 datacenter model with the value "dc-1"
+ And 3 node models
+ When I visit the nodes page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be /dc-1/nodes
+ Then I see 3 node models
diff --git a/ui-v2/tests/acceptance/dc/nodes/services.feature b/ui-v2/tests/acceptance/dc/nodes/services.feature
new file mode 100644
index 0000000000..d7c6713312
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/nodes/services.feature
@@ -0,0 +1,16 @@
+@setupApplicationTest
+Feature: Search services within nodes by name and port
+ Scenario: Given 1 node
+ Given 1 datacenter model with the value "dc1"
+ And 1 node models from yaml
+ ---
+ - ID: node-0
+ ---
+ When I visit the node page for yaml
+ ---
+ dc: dc1
+ node: node-0
+ ---
+ When I click services on the tabs
+ And I see servicesIsSelected on the tabs
+
diff --git a/ui-v2/tests/acceptance/dc/nodes/show.feature b/ui-v2/tests/acceptance/dc/nodes/show.feature
new file mode 100644
index 0000000000..49a8c22fa1
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/nodes/show.feature
@@ -0,0 +1,46 @@
+@setupApplicationTest
+Feature: Show node
+ Scenario: Given 2 nodes all the tabs are visible and clickable
+ Given 1 datacenter model with the value "dc1"
+ And 2 node models from yaml
+ ---
+ - ID: node-0
+ - ID: node-1
+ ---
+ When I visit the node page for yaml
+ ---
+ dc: dc1
+ node: node-0
+ ---
+ And I see healthChecksIsSelected on the tabs
+
+ When I click services on the tabs
+ And I see servicesIsSelected on the tabs
+
+ When I click roundTripTime on the tabs
+ And I see roundTripTimeIsSelected on the tabs
+
+ When I click lockSessions on the tabs
+ And I see lockSessionsIsSelected on the tabs
+@ignore
+ Scenario: Given 1 node all the tabs are visible and clickable and the RTT one isn't there
+ Given 1 datacenter model with the value "dc1"
+ And 1 node models from yaml
+ ---
+ - ID: node-0
+ ---
+ When I visit the node page for yaml
+ ---
+ dc: dc1
+ node: node-0
+ ---
+ And I see healthChecksIsSelected on the tabs
+
+ When I click services on the tabs
+ And I see servicesIsSelected on the tabs
+
+ And I don't see roundTripTime on the tabs
+
+ When I click lockSessions on the tabs
+ And I see lockSessionsIsSelected on the tabs
+
diff --git a/ui-v2/tests/acceptance/dc/services/index.feature b/ui-v2/tests/acceptance/dc/services/index.feature
new file mode 100644
index 0000000000..a70f62ba63
--- /dev/null
+++ b/ui-v2/tests/acceptance/dc/services/index.feature
@@ -0,0 +1,11 @@
+@setupApplicationTest
+Feature: Services
+ Scenario:
+ Given 1 datacenter model with the value "dc-1"
+ And 3 service models
+ When I visit the services page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be /dc-1/services
+ Then I see 3 service models
diff --git a/ui-v2/tests/acceptance/index-forwarding.feature b/ui-v2/tests/acceptance/index-forwarding.feature
new file mode 100644
index 0000000000..f467d8fcee
--- /dev/null
+++ b/ui-v2/tests/acceptance/index-forwarding.feature
@@ -0,0 +1,6 @@
+@setupApplicationTest
+Feature: index forwarding
+ Scenario: Arriving at the index page when there is only one datacenter
+ Given 1 datacenter model with the value "datacenter"
+ When I visit the index page
+ Then the url should be /datacenter/services
diff --git a/ui-v2/tests/acceptance/page-navigation.feature b/ui-v2/tests/acceptance/page-navigation.feature
new file mode 100644
index 0000000000..360b910757
--- /dev/null
+++ b/ui-v2/tests/acceptance/page-navigation.feature
@@ -0,0 +1,43 @@
+@setupApplicationTest
+Feature: Page Navigation
+ Background:
+ Given 1 datacenter model with the value "dc-1"
+ Scenario: Visiting the index page
+ When I visit the index page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be /dc-1/services
+ Scenario: Clicking [Link] in the navigation takes me to [Url]
+ When I visit the services page for yaml
+ ---
+ dc: dc-1
+ ---
+ When I click [Link] on the navigation
+ Then the url should be [Url]
+ Where:
+ --------------------------------------
+ | Link | Url |
+ | nodes | /dc-1/nodes |
+ | kvs | /dc-1/kv |
+ | acls | /dc-1/acls |
+ | settings | /settings |
+ --------------------------------------
+ Scenario: Clicking a [Item] in the [Model] listing
+ When I visit the [Model] page for yaml
+ ---
+ dc: dc-1
+ ---
+ When I click [Item] on the [Model]
+ Then the url should be [Url]
+ Where:
+ --------------------------------------------------------
+ | Item | Model | Url |
+ | service | services | /dc-1/services/service-0 |
+ | node | nodes | /dc-1/nodes/node-0 |
+ | kv | kvs | /dc-1/kv/necessitatibus-0/edit |
+ | acl | acls | /dc-1/acls/anonymous |
+ --------------------------------------------------------
+@ignore
+ Scenario: Clicking a kv in the kvs listing, without depending on the salt ^
+ Then ok
diff --git a/ui-v2/tests/acceptance/steps/components/acl-filter-steps.js b/ui-v2/tests/acceptance/steps/components/acl-filter-steps.js
new file mode 100644
index 0000000000..960cdf533d
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/components/acl-filter-steps.js
@@ -0,0 +1,10 @@
+import steps from '../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/components/catalog-filter-steps.js b/ui-v2/tests/acceptance/steps/components/catalog-filter-steps.js
new file mode 100644
index 0000000000..960cdf533d
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/components/catalog-filter-steps.js
@@ -0,0 +1,10 @@
+import steps from '../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/components/kv-filter-steps.js b/ui-v2/tests/acceptance/steps/components/kv-filter-steps.js
new file mode 100644
index 0000000000..960cdf533d
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/components/kv-filter-steps.js
@@ -0,0 +1,10 @@
+import steps from '../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/acls/delete-steps.js b/ui-v2/tests/acceptance/steps/dc/acls/delete-steps.js
new file mode 100644
index 0000000000..a7eff3228b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/acls/delete-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/acls/update-steps.js b/ui-v2/tests/acceptance/steps/dc/acls/update-steps.js
new file mode 100644
index 0000000000..ba1093295f
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/acls/update-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/index-steps.js b/ui-v2/tests/acceptance/steps/dc/index-steps.js
new file mode 100644
index 0000000000..960cdf533d
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/index-steps.js
@@ -0,0 +1,10 @@
+import steps from '../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/kv/index/view-kvs-steps.js b/ui-v2/tests/acceptance/steps/dc/kv/index/view-kvs-steps.js
new file mode 100644
index 0000000000..9bfbe9ac9b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/kv/index/view-kvs-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/kvs/delete-steps.js b/ui-v2/tests/acceptance/steps/dc/kvs/delete-steps.js
new file mode 100644
index 0000000000..a7eff3228b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/kvs/delete-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/kvs/list-order-steps.js b/ui-v2/tests/acceptance/steps/dc/kvs/list-order-steps.js
new file mode 100644
index 0000000000..a7eff3228b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/kvs/list-order-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/kvs/update-steps.js b/ui-v2/tests/acceptance/steps/dc/kvs/update-steps.js
new file mode 100644
index 0000000000..a7eff3228b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/kvs/update-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/list-steps.js b/ui-v2/tests/acceptance/steps/dc/list-steps.js
new file mode 100644
index 0000000000..960cdf533d
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/list-steps.js
@@ -0,0 +1,10 @@
+import steps from '../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/nodes/index-steps.js b/ui-v2/tests/acceptance/steps/dc/nodes/index-steps.js
new file mode 100644
index 0000000000..a7eff3228b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/nodes/index-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/nodes/index/view-nodes-steps.js b/ui-v2/tests/acceptance/steps/dc/nodes/index/view-nodes-steps.js
new file mode 100644
index 0000000000..9bfbe9ac9b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/nodes/index/view-nodes-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/nodes/services-steps.js b/ui-v2/tests/acceptance/steps/dc/nodes/services-steps.js
new file mode 100644
index 0000000000..a7eff3228b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/nodes/services-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/nodes/show-steps.js b/ui-v2/tests/acceptance/steps/dc/nodes/show-steps.js
new file mode 100644
index 0000000000..a7eff3228b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/nodes/show-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/services/index-steps.js b/ui-v2/tests/acceptance/steps/dc/services/index-steps.js
new file mode 100644
index 0000000000..a7eff3228b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/services/index-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/dc/services/index/view-services-steps.js b/ui-v2/tests/acceptance/steps/dc/services/index/view-services-steps.js
new file mode 100644
index 0000000000..9bfbe9ac9b
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/dc/services/index/view-services-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/index-forwarding-steps.js b/ui-v2/tests/acceptance/steps/index-forwarding-steps.js
new file mode 100644
index 0000000000..c900334997
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/index-forwarding-steps.js
@@ -0,0 +1,10 @@
+import steps from './steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/page-navigation-steps.js b/ui-v2/tests/acceptance/steps/page-navigation-steps.js
new file mode 100644
index 0000000000..c5f07c8043
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/page-navigation-steps.js
@@ -0,0 +1,10 @@
+import steps from './steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/steps/steps.js b/ui-v2/tests/acceptance/steps/steps.js
new file mode 100644
index 0000000000..df45d3f284
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/steps.js
@@ -0,0 +1,2 @@
+import steps from 'consul-ui/tests/steps';
+export default steps;
diff --git a/ui-v2/tests/acceptance/steps/submit-blank-steps.js b/ui-v2/tests/acceptance/steps/submit-blank-steps.js
new file mode 100644
index 0000000000..c5f07c8043
--- /dev/null
+++ b/ui-v2/tests/acceptance/steps/submit-blank-steps.js
@@ -0,0 +1,10 @@
+import steps from './steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui-v2/tests/acceptance/submit-blank.feature b/ui-v2/tests/acceptance/submit-blank.feature
new file mode 100644
index 0000000000..a8024a384d
--- /dev/null
+++ b/ui-v2/tests/acceptance/submit-blank.feature
@@ -0,0 +1,24 @@
+@setupApplicationTest
+Feature: submit blank
+ In order to prevent form's being saved without values
+ As a user
+ I shouldn't be able to submit a blank form
+ Scenario: Visiting a blank form for [Model]
+ Given 1 datacenter model with the value "datacenter"
+ When I visit the [Model] page for yaml
+ ---
+ dc: datacenter
+ ---
+ Then the url should be /datacenter/[Slug]/create
+ And I submit
+ Then the url should be /datacenter/[Slug]/create
+ Where:
+ ------------------
+ | Model | Slug |
+ | kv | kv |
+ | acl | acls |
+ ------------------
+@ignore
+ Scenario: The button is disabled
+ Then ok
+
diff --git a/ui-v2/tests/helpers/api.js b/ui-v2/tests/helpers/api.js
new file mode 100644
index 0000000000..800672103e
--- /dev/null
+++ b/ui-v2/tests/helpers/api.js
@@ -0,0 +1,4 @@
+import getAPI from '@hashicorp/ember-cli-api-double';
+import setCookies from 'consul-ui/tests/helpers/set-cookies';
+import typeToURL from 'consul-ui/tests/helpers/type-to-url';
+export default getAPI('/consul-api-double', setCookies, typeToURL);
diff --git a/ui-v2/tests/helpers/set-cookies.js b/ui-v2/tests/helpers/set-cookies.js
new file mode 100644
index 0000000000..04f0857636
--- /dev/null
+++ b/ui-v2/tests/helpers/set-cookies.js
@@ -0,0 +1,25 @@
+export default function(type, count, obj) {
+ var key = '';
+ switch (type) {
+ case 'dc':
+ key = 'CONSUL_DATACENTER_COUNT';
+ break;
+ case 'service':
+ key = 'CONSUL_SERVICE_COUNT';
+ break;
+ case 'node':
+ key = 'CONSUL_NODE_COUNT';
+ break;
+ case 'kv':
+ key = 'CONSUL_KV_COUNT';
+ break;
+ case 'acl':
+ key = 'CONSUL_ACL_COUNT';
+ obj['CONSUL_ENABLE_ACLS'] = 1;
+ break;
+ }
+ if (key) {
+ obj[key] = count;
+ }
+ return obj;
+}
diff --git a/ui-v2/tests/helpers/type-to-url.js b/ui-v2/tests/helpers/type-to-url.js
new file mode 100644
index 0000000000..68446a8b7c
--- /dev/null
+++ b/ui-v2/tests/helpers/type-to-url.js
@@ -0,0 +1,23 @@
+export default function(type) {
+ let url = null;
+ switch (type) {
+ case 'dc':
+ url = '/v1/catalog/datacenters';
+ break;
+ case 'service':
+ url = '/v1/internal/ui/services';
+ break;
+ case 'node':
+ url = '/v1/internal/ui/nodes';
+ // url = '/v1/health/service/_';
+ break;
+ case 'kv':
+ url = '/v1/kv/';
+ break;
+ case 'acl':
+ url = '/v1/acl/list';
+ // url = '/v1/acl/info/_';
+ break;
+ }
+ return url;
+}
diff --git a/ui-v2/tests/helpers/yadda-annotations.js b/ui-v2/tests/helpers/yadda-annotations.js
new file mode 100644
index 0000000000..bb7b427c16
--- /dev/null
+++ b/ui-v2/tests/helpers/yadda-annotations.js
@@ -0,0 +1,85 @@
+import ENV from '../../config/environment';
+import { skip } from 'qunit';
+import { setupApplicationTest, setupRenderingTest, setupTest } from 'ember-qunit';
+import api from 'consul-ui/tests/helpers/api';
+
+// this logic could be anything, but in this case...
+// if @ignore, then return skip (for backwards compatibility)
+// if have annotations in config, then only run those that have a matching annotation
+function checkAnnotations(annotations) {
+ // if ignore is set then we want to skip for backwards compatibility
+ if (annotations.ignore) {
+ return ignoreIt;
+ }
+
+ // if have annotations set in config, the only run those that have a matching annotation
+ if (ENV.annotations && ENV.annotations.length >= 0) {
+ for (let annotation in annotations) {
+ if (ENV.annotations.indexOf(annotation) >= 0) {
+ // have match, so test it
+ return 'testIt'; // return something other than a function
+ }
+ }
+
+ // no match, so don't run it
+ return logIt;
+ }
+}
+
+// call back functions
+function ignoreIt(testElement) {
+ skip(`${testElement.title}`, function(/*assert*/) {});
+}
+
+function logIt(testElement) {
+ console.info(`Not running or skipping: "${testElement.title}"`); // eslint-disable-line no-console
+}
+
+// exported functions
+function runFeature(annotations) {
+ return checkAnnotations(annotations);
+}
+
+function runScenario(featureAnnotations, scenarioAnnotations) {
+ return checkAnnotations(scenarioAnnotations);
+}
+
+// setup tests
+// you can override these function to add additional setup setups, or handle new setup related annotations
+function setupFeature(featureAnnotations) {
+ return setupYaddaTest(featureAnnotations);
+}
+
+function setupScenario(featureAnnotations, scenarioAnnotations) {
+ let setupFn = setupYaddaTest(scenarioAnnotations);
+ if (
+ setupFn &&
+ (featureAnnotations.setupapplicationtest ||
+ featureAnnotations.setuprenderingtest ||
+ featureAnnotations.setuptest)
+ ) {
+ throw new Error(
+ 'You must not assign any @setupapplicationtest, @setuprenderingtest or @setuptest annotations to a scenario as well as its feature!'
+ );
+ }
+ return function(model) {
+ model.afterEach(function() {
+ api.server.reset();
+ });
+ };
+ // return setupFn;
+}
+
+function setupYaddaTest(annotations) {
+ if (annotations.setupapplicationtest) {
+ return setupApplicationTest;
+ }
+ if (annotations.setuprenderingtest) {
+ return setupRenderingTest;
+ }
+ if (annotations.setuptest) {
+ return setupTest;
+ }
+}
+
+export { runFeature, runScenario, setupFeature, setupScenario };
diff --git a/ui-v2/tests/helpers/yadda.js b/ui-v2/tests/helpers/yadda.js
new file mode 100644
index 0000000000..dfdc1024a0
--- /dev/null
+++ b/ui-v2/tests/helpers/yadda.js
@@ -0,0 +1,2 @@
+import yadda from 'npm:yadda';
+export default yadda;
diff --git a/ui-v2/tests/integration/helpers/left-trim-test.js b/ui-v2/tests/integration/helpers/left-trim-test.js
index 587e789a16..805ae93824 100644
--- a/ui-v2/tests/integration/helpers/left-trim-test.js
+++ b/ui-v2/tests/integration/helpers/left-trim-test.js
@@ -1,4 +1,4 @@
-import { moduleForComponent, skip } from 'ember-qunit';
+import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('left trim', 'helper:left-trim', {
@@ -6,7 +6,7 @@ moduleForComponent('left trim', 'helper:left-trim', {
});
// Replace this with your real tests.
-skip('it renders', function(assert) {
+test('it renders', function(assert) {
this.set('inputValue', '1234');
this.render(hbs`{{left-trim inputValue}}`);
diff --git a/ui-v2/tests/integration/helpers/right-trim-test.js b/ui-v2/tests/integration/helpers/right-trim-test.js
index 7e0ccac8a7..0cb91cadb8 100644
--- a/ui-v2/tests/integration/helpers/right-trim-test.js
+++ b/ui-v2/tests/integration/helpers/right-trim-test.js
@@ -1,4 +1,4 @@
-import { moduleForComponent, skip } from 'ember-qunit';
+import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('right-trim', 'helper:right-trim', {
@@ -6,7 +6,7 @@ moduleForComponent('right-trim', 'helper:right-trim', {
});
// Replace this with your real tests.
-skip('it renders', function(assert) {
+test('it renders', function(assert) {
this.set('inputValue', '1234');
this.render(hbs`{{right-trim inputValue}}`);
diff --git a/ui-v2/tests/lib/page-object/visitable.js b/ui-v2/tests/lib/page-object/visitable.js
new file mode 100644
index 0000000000..c6abebc637
--- /dev/null
+++ b/ui-v2/tests/lib/page-object/visitable.js
@@ -0,0 +1,84 @@
+// import { assign } from '../-private/helpers';
+const assign = Object.assign;
+import { getExecutionContext } from 'ember-cli-page-object/-private/execution_context';
+
+import $ from '-jquery';
+
+function fillInDynamicSegments(path, params, encoder) {
+ return path
+ .split('/')
+ .map(function(segment) {
+ let match = segment.match(/^:(.+)$/);
+
+ if (match) {
+ let [, key] = match;
+ let value = params[key];
+
+ if (typeof value === 'undefined') {
+ throw new Error(`Missing parameter for '${key}'`);
+ }
+
+ // Remove dynamic segment key from params
+ delete params[key];
+ return encoder(value);
+ }
+
+ return segment;
+ })
+ .join('/');
+}
+
+function appendQueryParams(path, queryParams) {
+ if (Object.keys(queryParams).length) {
+ path += `?${$.param(queryParams)}`;
+ }
+
+ return path;
+}
+/**
+ * Custom implementation of `visitable`
+ * Currently aims to be compatible and as close as possible to the
+ * actual `ember-cli-page-object` version
+ *
+ * Additions:
+ * 1. Injectable encoder, for when you don't want your segments to be encoded
+ * or you have specific encoding needs
+ * Specifically in my case for KV urls where the `Key`/Slug shouldn't be encoded,
+ * defaults to the browsers `encodeURIComponent` for compatibility and ease.
+ * 2. `path` can be an array of (string) paths OR a string for compatibility.
+ * If a path cannot be generated due to a lack of properties on the
+ * dynamic segment params, if will keep trying 'path' in the array
+ * until it finds one that it can construct. This follows the same thinking
+ * as 'if you don't specify an item, then we are looking to create one'
+ */
+export function visitable(path, encoder = encodeURIComponent) {
+ return {
+ isDescriptor: true,
+
+ value(dynamicSegmentsAndQueryParams = {}) {
+ let executionContext = getExecutionContext(this);
+
+ return executionContext.runAsync(context => {
+ var params;
+ let fullPath = (function _try(paths) {
+ const path = paths.shift();
+ params = assign({}, dynamicSegmentsAndQueryParams);
+ var fullPath;
+ try {
+ fullPath = fillInDynamicSegments(path, params, encoder);
+ } catch (e) {
+ if (paths.length > 0) {
+ fullPath = _try(paths);
+ } else {
+ throw e;
+ }
+ }
+ return fullPath;
+ })(typeof path === 'string' ? [path] : path.slice(0));
+ fullPath = appendQueryParams(fullPath, params);
+
+ return context.visit(fullPath);
+ });
+ },
+ };
+}
diff --git a/ui-v2/tests/pages/dc/acls/edit.js b/ui-v2/tests/pages/dc/acls/edit.js
index 2fb1367868..d15301ef46 100644
--- a/ui-v2/tests/pages/dc/acls/edit.js
+++ b/ui-v2/tests/pages/dc/acls/edit.js
@@ -1,7 +1,10 @@
-import { create, visitable, fillable, clickable } from 'ember-cli-page-object';
+import { create, clickable, triggerable } from 'ember-cli-page-object';
+import { visitable } from 'consul-ui/tests/lib/page-object/visitable';
export default create({
- visit: visitable('/:dc/acls/:acl'),
- fillIn: fillable('input, textarea, [contenteditable]'),
+ // custom visitable
+ visit: visitable(['/:dc/acls/:acl', '/:dc/acls/create']),
+ // fillIn: fillable('input, textarea, [contenteditable]'),
+ name: triggerable('keypress', '[name="name"]'),
submit: clickable('[type=submit]'),
});
diff --git a/ui-v2/tests/pages/dc/acls/index.js b/ui-v2/tests/pages/dc/acls/index.js
index be5881be83..7b03bb7586 100644
--- a/ui-v2/tests/pages/dc/acls/index.js
+++ b/ui-v2/tests/pages/dc/acls/index.js
@@ -3,9 +3,12 @@ import { create, visitable, collection, attribute, clickable } from 'ember-cli-p
import filter from 'consul-ui/tests/pages/components/acl-filter';
export default create({
visit: visitable('/:dc/acls'),
- acls: collection('[data-test-acl]', {
- name: attribute('data-test-acl'),
+ acls: collection('[data-test-tabular-row]', {
+ name: attribute('data-test-acl', '[data-test-acl]'),
acl: clickable('a'),
+ actions: clickable('label'),
+ delete: clickable('li:last-child a'),
+ confirmDelete: clickable('button.type-delete'),
}),
filter: filter,
});
diff --git a/ui-v2/tests/pages/dc/kv/edit.js b/ui-v2/tests/pages/dc/kv/edit.js
index 8dab1a3265..c8af7bae0f 100644
--- a/ui-v2/tests/pages/dc/kv/edit.js
+++ b/ui-v2/tests/pages/dc/kv/edit.js
@@ -1,7 +1,10 @@
-import { create, visitable, fillable, clickable } from 'ember-cli-page-object';
+import { create, clickable } from 'ember-cli-page-object';
+import { visitable } from 'consul-ui/tests/lib/page-object/visitable';
export default create({
- visit: visitable('/:dc/kv/:kv'),
- fillIn: fillable('input, textarea, [contenteditable]'),
+ // custom visitable
+ visit: visitable(['/:dc/kv/:kv/edit', '/:dc/kv/create'], str => str),
+ // fillIn: fillable('input, textarea, [contenteditable]'),
+ // name: triggerable('keypress', '[name="additional"]'),
submit: clickable('[type=submit]'),
});
diff --git a/ui-v2/tests/pages/dc/kv/index.js b/ui-v2/tests/pages/dc/kv/index.js
index fb11214ea9..08c2237787 100644
--- a/ui-v2/tests/pages/dc/kv/index.js
+++ b/ui-v2/tests/pages/dc/kv/index.js
@@ -1,6 +1,12 @@
-import { create, visitable, collection } from 'ember-cli-page-object';
+import { create, visitable, collection, attribute, clickable } from 'ember-cli-page-object';
export default create({
visit: visitable('/:dc/kv'),
- kvs: collection('[data-test-kv]'),
+ kvs: collection('[data-test-tabular-row]', {
+ name: attribute('data-test-kv', '[data-test-kv]'),
+ kv: clickable('a'),
+ actions: clickable('label'),
+ delete: clickable('li:last-child a'),
+ confirmDelete: clickable('button.type-delete'),
+ }),
});
diff --git a/ui-v2/tests/pages/dc/nodes/show.js b/ui-v2/tests/pages/dc/nodes/show.js
index b10f8f9e51..577a03ae2a 100644
--- a/ui-v2/tests/pages/dc/nodes/show.js
+++ b/ui-v2/tests/pages/dc/nodes/show.js
@@ -1,7 +1,13 @@
-import { create, visitable } from 'ember-cli-page-object';
+import { create, visitable, collection, attribute } from 'ember-cli-page-object';
import radiogroup from 'consul-ui/tests/lib/page-object/radiogroup';
export default create({
visit: visitable('/:dc/nodes/:node'),
tabs: radiogroup('tab', ['health-checks', 'services', 'round-trip-time', 'lock-sessions']),
+ healthchecks: collection('[data-test-node-healthcheck]', {
+ name: attribute('data-test-node-healthcheck'),
+ }),
+ services: collection('#services [data-test-tabular-row]', {
+ port: attribute('data-test-service-port', '.port'),
+ }),
});
diff --git a/ui-v2/tests/steps.js b/ui-v2/tests/steps.js
new file mode 100644
index 0000000000..98208ac03c
--- /dev/null
+++ b/ui-v2/tests/steps.js
@@ -0,0 +1,239 @@
+/* eslint no-console: "off" */
+import yadda from './helpers/yadda';
+import { currentURL, click, triggerKeyEvent } from '@ember/test-helpers';
+import getDictionary from '@hashicorp/ember-cli-api-double/dictionary';
+import pages from 'consul-ui/tests/pages';
+import api from 'consul-ui/tests/helpers/api';
+
+const create = function(number, name, value) {
+ // don't return a promise here as
+ // I don't need it to wait
+ api.server.createList(name, number, value);
+};
+var currentPage;
+export default function(assert) {
+ return (
+ yadda.localisation.English.library(
+ getDictionary(function(model, cb) {
+ switch (model) {
+ case 'datacenter':
+ case 'datacenters':
+ case 'dcs':
+ model = 'dc';
+ break;
+ case 'services':
+ model = 'service';
+ break;
+ case 'nodes':
+ model = 'node';
+ break;
+ case 'kvs':
+ model = 'kv';
+ break;
+ case 'acls':
+ model = 'acl';
+ break;
+ }
+ cb(null, model);
+ }, yadda)
+ )
+ // doubles
+ .given(['$number $model model', '$number $model models'], function(number, model) {
+ return create(number, model);
+ })
+ .given(['$number $model model with the value "$value"'], function(number, model, value) {
+ return create(number, model, value);
+ })
+ .given(
+ ['$number $model model[s]? from yaml\n$yaml', '$number $model model from json\n$json'],
+ function(number, model, data) {
+ return create(number, model, data);
+ }
+ )
+ // interactions
+ .when('I visit the $name page', function(name) {
+ currentPage = pages[name];
+ return currentPage.visit();
+ })
+ .when('I visit the $name page for the "$id" $model', function(name, id, model) {
+ currentPage = pages[name];
+ return currentPage.visit({
+ [model]: id,
+ });
+ })
+ .when(
+ ['I visit the $name page for yaml\n$yaml', 'I visit the $name page for json\n$json'],
+ function(name, data) {
+ currentPage = pages[name];
+ // TODO: Consider putting an assertion here for testing the current url
+ // do I absolutely definitely need that all the time?
+ return pages[name].visit(data);
+ }
+ )
+ .when('I click "$selector"', function(selector) {
+ return click(selector);
+ })
+ .when('I click $prop on the $component', function(prop, component) {
+ // Collection
+ var obj;
+ if (typeof currentPage[component].objectAt === 'function') {
+ obj = currentPage[component].objectAt(0);
+ } else {
+ obj = currentPage[component];
+ }
+ const func = obj[prop].bind(obj);
+ try {
+ return func();
+ } catch (e) {
+ console.error(e);
+ throw new Error(`The '${prop}' property on the '${component}' page object doesn't exist`);
+ }
+ })
+ .when('I submit', function(selector) {
+ return currentPage.submit();
+ })
+ .then('I fill in "$name" with "$value"', function(name, value) {
+ return currentPage.fillIn(name, value);
+ })
+ .then(['I fill in with yaml\n$yaml', 'I fill in with json\n$json'], function(data) {
+ return Object.keys(data).reduce(function(prev, item, i, arr) {
+ return prev.fillIn(item, data[item]);
+ }, currentPage);
+ })
+ .then(['I type with yaml\n$yaml'], function(data) {
+ const keys = Object.keys(data);
+ return keys
+ .reduce(function(prev, item, i, arr) {
+ return prev.fillIn(item, data[item]);
+ }, currentPage)
+ .then(function() {
+ return Promise.all(
+ keys.map(function(item) {
+ return triggerKeyEvent(`[name="${item}"]`, 'keyup', 83);
+ })
+ );
+ });
+ })
+ // debugging helpers
+ .then('print the current url', function(url) {
+ console.log(currentURL());
+ return Promise.resolve();
+ })
+ .then('log the "$text"', function(text) {
+ console.log(text);
+ return Promise.resolve();
+ })
+ .then('pause for $milliseconds', function(milliseconds) {
+ return new Promise(function(resolve) {
+ setTimeout(resolve, milliseconds);
+ });
+ })
+ // assertions
+ .then('a $method request is made to "$url" with the body from yaml\n$yaml', function(
+ method,
+ url,
+ data
+ ) {
+ const request = api.server.history[api.server.history.length - 2];
+ assert.equal(
+ request.method,
+ method,
+ `Expected the request method to be ${method}, was ${request.method}`
+ );
+ assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
+ const body = JSON.parse(request.requestBody);
+ Object.keys(data).forEach(function(key, i, arr) {
+ assert.equal(
+ body[key],
+ data[key],
+ `Expected the payload to contain ${key} to equal ${body[key]}, ${key} was ${data[key]}`
+ );
+ });
+ })
+ .then('a $method request is made to "$url" with the body "$body"', function(
+ method,
+ url,
+ data
+ ) {
+ const request = api.server.history[api.server.history.length - 2];
+ assert.equal(
+ request.method,
+ method,
+ `Expected the request method to be ${method}, was ${request.method}`
+ );
+ assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
+ const body = request.requestBody;
+ assert.equal(
+ body,
+ data,
+ `Expected the request body to be ${body}, was ${request.requestBody}`
+ );
+ })
+ .then('a $method request is made to "$url"', function(method, url) {
+ const request = api.server.history[api.server.history.length - 2];
+ assert.equal(
+ request.method,
+ method,
+ `Expected the request method to be ${method}, was ${request.method}`
+ );
+ assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
+ })
+ .then('the url should be $url', function(url) {
+ const current = currentURL();
+ assert.equal(current, url, `Expected the url to be ${url} was ${current}`);
+ })
+ .then(['I see $num $model', 'I see $num $model model', 'I see $num $model models'], function(
+ num,
+ model
+ ) {
+ const len = currentPage[`${model}s`].filter(function(item) {
+ return item.isVisible;
+ }).length;
+
+ assert.equal(len, num, `Expected ${num} ${model}s, saw ${len}`);
+ })
+ .then(['I see $num $model model with the $property "$value"'], function(
+ num,
+ model,
+ property,
+ value
+ ) {
+ const len = currentPage[`${model}s`].filter(function(item) {
+ return item.isVisible && item[property] == value;
+ }).length;
+ assert.equal(
+ len,
+ num,
+ `Expected ${num} ${model}s with ${property} set to "${value}", saw ${len}`
+ );
+ })
+ .then('I see $property on the $component like yaml\n$yaml', function(
+ property,
+ component,
+ yaml
+ ) {
+ const _component = currentPage[component];
+ const iterator = new Array(_component.length).fill(true);
+ iterator.forEach(function(item, i, arr) {
+ const actual = _component.objectAt(i)[property];
+ const expected = yaml[i];
+ assert.deepEqual(
+ actual,
+ expected,
+ `Expected to see ${property} on ${component}[${i}] as ${JSON.stringify(
+ expected
+ )}, was ${JSON.stringify(actual)}`
+ );
+ });
+ })
+ .then(['I see $property on the $component'], function(property, component) {
+ assert.ok(currentPage[component][property], `Expected to see ${property} on ${component}`);
+ })
+ .then(['I see $property'], function(property, component) {
+ assert.ok(currentPage[property], `Expected to see ${property}`);
+ })
+ .then('ok', function() {
+ assert.ok(true);
+ })
+ );
+}
diff --git a/ui-v2/tests/unit/controllers/dc/kv/folder-test.js b/ui-v2/tests/unit/controllers/dc/kv/folder-test.js
new file mode 100644
index 0000000000..c9edb0e623
--- /dev/null
+++ b/ui-v2/tests/unit/controllers/dc/kv/folder-test.js
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('controller:dc/kv/folder', 'Unit | Controller | dc/kv/folder', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+ let controller = this.subject();
+ assert.ok(controller);
+});
diff --git a/ui-v2/tests/unit/controllers/dc/kv/index-test.js b/ui-v2/tests/unit/controllers/dc/kv/index-test.js
new file mode 100644
index 0000000000..af2dfbad18
--- /dev/null
+++ b/ui-v2/tests/unit/controllers/dc/kv/index-test.js
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('controller:dc/kv/index', 'Unit | Controller | dc/kv/index', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+ let controller = this.subject();
+ assert.ok(controller);
+});
diff --git a/ui-v2/tests/unit/utils/get-component-factory-test.js b/ui-v2/tests/unit/utils/get-component-factory-test.js
new file mode 100644
index 0000000000..16be5c677e
--- /dev/null
+++ b/ui-v2/tests/unit/utils/get-component-factory-test.js
@@ -0,0 +1,48 @@
+import getComponentFactory from 'consul-ui/utils/get-component-factory';
+import { module, test } from 'qunit';
+
+module('Unit | Utility | get component factory');
+
+test("it uses lookup to locate the instance of the component based on the DOM element's id", function(assert) {
+ const expected = 'name';
+ let getComponent = getComponentFactory({
+ lookup: function() {
+ return { id: expected };
+ },
+ });
+ assert.equal(typeof getComponent, 'function', 'returns a function');
+ const actual = getComponent({
+ getAttribute: function(name) {
+ return 'id';
+ },
+ });
+ assert.equal(actual, expected, 'performs a lookup based on the id');
+});
+test("it returns null if it can't find it", function(assert) {
+ const expected = null;
+ let getComponent = getComponentFactory({
+ lookup: function() {
+ return { id: '' };
+ },
+ });
+ const actual = getComponent({
+ getAttribute: function(name) {
+ return 'non-existent';
+ },
+ });
+ assert.equal(actual, expected);
+});
+test('it returns null if there is no id', function(assert) {
+ const expected = null;
+ let getComponent = getComponentFactory({
+ lookup: function() {
+ return { id: '' };
+ },
+ });
+ const actual = getComponent({
+ getAttribute: function(name) {
+ return;
+ },
+ });
+ assert.equal(actual, expected);
+});
diff --git a/ui-v2/tests/unit/utils/hasStatus-test.js b/ui-v2/tests/unit/utils/hasStatus-test.js
new file mode 100644
index 0000000000..6ddfe37a1d
--- /dev/null
+++ b/ui-v2/tests/unit/utils/hasStatus-test.js
@@ -0,0 +1,19 @@
+import hasStatus from 'consul-ui/utils/hasStatus';
+import { module, test, skip } from 'qunit';
+
+module('Unit | Utility | has status');
+
+const checks = {
+ filterBy: function(prop, value) {
+ return { length: 0 };
+ },
+};
+test('it returns true when passing an empty string (therefore "all")', function(assert) {
+ assert.ok(hasStatus(checks, ''));
+});
+test('it returns false when passing an actual status', function(assert) {
+ ['passing', 'critical', 'warning'].forEach(function(item) {
+ assert.ok(!hasStatus(checks, item), `, with ${item}`);
+ });
+});
+skip('it works as a factory, passing ember `get` in to create the function');
diff --git a/ui-v2/tests/unit/utils/left-trim-test.js b/ui-v2/tests/unit/utils/left-trim-test.js
new file mode 100644
index 0000000000..03e38a7074
--- /dev/null
+++ b/ui-v2/tests/unit/utils/left-trim-test.js
@@ -0,0 +1,44 @@
+import { module } from 'ember-qunit';
+import test from 'ember-sinon-qunit/test-support/test';
+import leftTrim from 'consul-ui/utils/left-trim';
+module('Unit | Utility | left trim');
+
+test('it trims characters from the left hand side', function(assert) {
+ [
+ {
+ args: ['/a/folder/here', '/'],
+ expected: 'a/folder/here',
+ },
+ {
+ args: ['/a/folder/here', ''],
+ expected: '/a/folder/here',
+ },
+ {
+ args: ['a/folder/here', '/'],
+ expected: 'a/folder/here',
+ },
+ {
+ args: ['a/folder/here/', '/'],
+ expected: 'a/folder/here/',
+ },
+ {
+ args: [],
+ expected: '',
+ },
+ {
+ args: ['/a/folder/here', '/a/folder'],
+ expected: '/here',
+ },
+ {
+ args: ['/a/folder/here/', '/a/folder/here'],
+ expected: '/',
+ },
+ {
+ args: ['/a/folder/here/', '/a/folder/here/'],
+ expected: '',
+ },
+ ].forEach(function(item) {
+ const actual = leftTrim(...item.args);
+ assert.equal(actual, item.expected);
+ });
+});
diff --git a/ui-v2/tests/unit/utils/qsa-factory-test.js b/ui-v2/tests/unit/utils/qsa-factory-test.js
new file mode 100644
index 0000000000..feadc8c3f5
--- /dev/null
+++ b/ui-v2/tests/unit/utils/qsa-factory-test.js
@@ -0,0 +1,34 @@
+import qsaFactory from 'consul-ui/utils/qsa-factory';
+import { module, test } from 'qunit';
+
+module('Unit | Utility | qsa factory');
+
+test('querySelectorAll is called on `document` when called with document', function(assert) {
+ assert.expect(2);
+ const expected = 'html';
+ const $$ = qsaFactory({
+ querySelectorAll: function(sel) {
+ assert.equal(sel, expected);
+ return true;
+ },
+ });
+ assert.ok($$(expected));
+});
+test('querySelectorAll is called on `context` when called with context', function(assert) {
+ assert.expect(2);
+ const expected = 'html';
+ const context = {
+ querySelectorAll: function(sel) {
+ assert.equal(sel, expected);
+ return true;
+ },
+ };
+ const $$ = qsaFactory({
+ // this should never be called
+ querySelectorAll: function(sel) {
+ assert.equal(sel, expected);
+ return false;
+ },
+ });
+ assert.ok($$(expected, context));
+});
diff --git a/ui-v2/tests/unit/utils/right-trim-test.js b/ui-v2/tests/unit/utils/right-trim-test.js
new file mode 100644
index 0000000000..567a2a4221
--- /dev/null
+++ b/ui-v2/tests/unit/utils/right-trim-test.js
@@ -0,0 +1,44 @@
+import { module } from 'ember-qunit';
+import test from 'ember-sinon-qunit/test-support/test';
+import rightTrim from 'consul-ui/utils/right-trim';
+module('Unit | Utility | right trim');
+
+test('it trims characters from the right hand side', function(assert) {
+ [
+ {
+ args: ['/a/folder/here/', '/'],
+ expected: '/a/folder/here',
+ },
+ {
+ args: ['/a/folder/here', ''],
+ expected: '/a/folder/here',
+ },
+ {
+ args: ['a/folder/here', '/'],
+ expected: 'a/folder/here',
+ },
+ {
+ args: ['a/folder/here/', '/'],
+ expected: 'a/folder/here',
+ },
+ {
+ args: [],
+ expected: '',
+ },
+ {
+ args: ['/a/folder/here', '/folder/here'],
+ expected: '/a',
+ },
+ {
+ args: ['/a/folder/here', 'a/folder/here'],
+ expected: '/',
+ },
+ {
+ args: ['/a/folder/here/', '/a/folder/here/'],
+ expected: '',
+ },
+ ].forEach(function(item) {
+ const actual = rightTrim(...item.args);
+ assert.equal(actual, item.expected);
+ });
+});
diff --git a/ui-v2/tests/unit/utils/sumOfUnhealthy-test.js b/ui-v2/tests/unit/utils/sumOfUnhealthy-test.js
new file mode 100644
index 0000000000..a8766db048
--- /dev/null
+++ b/ui-v2/tests/unit/utils/sumOfUnhealthy-test.js
@@ -0,0 +1,93 @@
+import sumOfUnhealthy from 'consul-ui/utils/sumOfUnhealthy';
+import { module, test, skip } from 'qunit';
+
+module('Unit | Utility | sum of unhealthy');
+
+test('it returns the correct single count', function(assert) {
+ const expected = 1;
+ [
+ [
+ {
+ Status: 'critical',
+ },
+ ],
+ [
+ {
+ Status: 'warning',
+ },
+ ],
+ ].forEach(function(checks) {
+ const actual = sumOfUnhealthy(checks);
+ assert.equal(actual, expected);
+ });
+});
+test('it returns the correct single count when there are none', function(assert) {
+ const expected = 0;
+ [
+ [
+ {
+ Status: 'passing',
+ },
+ {
+ Status: 'passing',
+ },
+ {
+ Status: 'passing',
+ },
+ {
+ Status: 'passing',
+ },
+ ],
+ [
+ {
+ Status: 'passing',
+ },
+ ],
+ ].forEach(function(checks) {
+ const actual = sumOfUnhealthy(checks);
+ assert.equal(actual, expected);
+ });
+});
+test('it returns the correct multiple count', function(assert) {
+ const expected = 3;
+ [
+ [
+ {
+ Status: 'critical',
+ },
+ {
+ Status: 'warning',
+ },
+ {
+ Status: 'warning',
+ },
+ {
+ Status: 'passing',
+ },
+ ],
+ [
+ {
+ Status: 'passing',
+ },
+ {
+ Status: 'critical',
+ },
+ {
+ Status: 'passing',
+ },
+ {
+ Status: 'warning',
+ },
+ {
+ Status: 'warning',
+ },
+ {
+ Status: 'passing',
+ },
+ ],
+ ].forEach(function(checks) {
+ const actual = sumOfUnhealthy(checks);
+ assert.equal(actual, expected);
+ });
+});
+skip('it works as a factory, passing ember `get` in to create the function');
diff --git a/ui-v2/yarn.lock b/ui-v2/yarn.lock
index 5a0db64a7b..c760ef53b3 100644
--- a/ui-v2/yarn.lock
+++ b/ui-v2/yarn.lock
@@ -17,6 +17,48 @@
ember-cli-babel "^6.10.0"
ember-cli-htmlbars-inline-precompile "^1.0.0"
+"@gardenhq/component-factory@^1.4.0":
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/@gardenhq/component-factory/-/component-factory-1.4.0.tgz#f5da8ddf2050fde9c69f4426d61fe55de043e78d"
+ dependencies:
+ "@gardenhq/domino" "^1.0.0"
+ "@gardenhq/tick-control" "^2.0.0"
+ classtrophobic-es5 "^0.2.1"
+ hyperhtml "^0.15.5"
+
+"@gardenhq/domino@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@gardenhq/domino/-/domino-1.0.0.tgz#832c493f3f05697b7df4ccce00c4cf620dc60923"
+ optionalDependencies:
+ min-document "^2.19.0"
+ unfetch "^2.1.2"
+ xhr2 "^0.1.4"
+
+"@gardenhq/o@^8.0.1":
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/@gardenhq/o/-/o-8.0.1.tgz#d6772cec7e4295a951165284cf43fbd0a373b779"
+ dependencies:
+ "@gardenhq/component-factory" "^1.4.0"
+ "@gardenhq/tick-control" "^2.0.0"
+ "@gardenhq/willow" "^6.2.0"
+ babel-standalone "^6.24.2"
+ file-saver "^1.3.3"
+ mousetrap "^1.6.1"
+ ncp "^2.0.0"
+ rollup "^0.41.6"
+ rollup-plugin-memory "^2.0.0"
+ uglify-es "^3.0.17"
+ optionalDependencies:
+ js-yaml "^3.8.4"
+
+"@gardenhq/tick-control@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@gardenhq/tick-control/-/tick-control-2.0.0.tgz#f84fe38ca7a09b7b2b52f42945c50429ba639897"
+
+"@gardenhq/willow@^6.2.0":
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/@gardenhq/willow/-/willow-6.2.0.tgz#3e4bc220a89099732746ead3385cc097bfb70186"
+
"@glimmer/di@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@glimmer/di/-/di-0.2.0.tgz#73bfd4a6ee4148a80bf092e8a5d29bcac9d4ce7e"
@@ -27,12 +69,46 @@
dependencies:
"@glimmer/di" "^0.2.0"
+"@hashicorp/api-double@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@hashicorp/api-double/-/api-double-1.1.0.tgz#299d3c560090dfe9c335db64d63c3ef0c5da79c4"
+ dependencies:
+ "@gardenhq/o" "^8.0.1"
+ "@gardenhq/tick-control" "^2.0.0"
+ array-range "^1.0.1"
+ cookie-parser "^1.4.3"
+ express "^4.16.2"
+ faker "^4.1.0"
+ js-yaml "^3.10.0"
+
+"@hashicorp/consul-api-double@^1.0.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@hashicorp/consul-api-double/-/consul-api-double-1.1.0.tgz#658f9e89208fa23f251ca66c66aeb7241a13f23f"
+
+"@hashicorp/ember-cli-api-double@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@hashicorp/ember-cli-api-double/-/ember-cli-api-double-1.0.2.tgz#684d418cc2a981254cc23035ceb452c86f0cd934"
+ dependencies:
+ "@hashicorp/api-double" "^1.1.0"
+ array-range "^1.0.1"
+ ember-cli-babel "^6.6.0"
+ js-yaml "^3.11.0"
+ pretender "^2.0.0"
+
"@sinonjs/formatio@^2.0.0":
version "2.0.0"
resolved "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2"
dependencies:
samsam "1.3.0"
+"@types/estree@0.0.38":
+ version "0.0.38"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.38.tgz#c1be40aa933723c608820a99a373a16d215a1ca2"
+
+"@types/node@*":
+ version "10.0.8"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.0.8.tgz#37b4d91d4e958e4c2ba0be2b86e7ed4ff19b0858"
+
JSONStream@^1.0.3:
version "1.3.2"
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea"
@@ -257,6 +333,10 @@ array-map@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662"
+array-range@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/array-range/-/array-range-1.0.1.tgz#f56e46591843611c6a56f77ef02eda7c50089bfc"
+
array-reduce@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b"
@@ -1023,6 +1103,10 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
+babel-standalone@^6.24.2:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-standalone/-/babel-standalone-6.26.0.tgz#15fb3d35f2c456695815ebf1ed96fe7f015b6886"
+
babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
@@ -1391,7 +1475,7 @@ broccoli-config-replace@^1.1.2:
debug "^2.2.0"
fs-extra "^0.24.0"
-broccoli-debug@^0.6.1, broccoli-debug@^0.6.2, broccoli-debug@^0.6.3:
+broccoli-debug@^0.6.1, broccoli-debug@^0.6.2, broccoli-debug@^0.6.3, broccoli-debug@^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/broccoli-debug/-/broccoli-debug-0.6.4.tgz#986eb3d2005e00e3bb91f9d0a10ab137210cd150"
dependencies:
@@ -1842,6 +1926,10 @@ builtin-modules@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+builtin-modules@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e"
+
builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
@@ -2058,6 +2146,10 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
+classtrophobic-es5@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/classtrophobic-es5/-/classtrophobic-es5-0.2.1.tgz#9bbfa62a9928abf26f385440032fb49da1cda88f"
+
clean-base-url@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/clean-base-url/-/clean-base-url-1.0.0.tgz#c901cf0a20b972435b0eccd52d056824a4351b7b"
@@ -2376,6 +2468,13 @@ convert-source-map@~1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860"
+cookie-parser@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.3.tgz#0fe31fa19d000b95f4aadf1f53fdc2b8a203baa5"
+ dependencies:
+ cookie "0.3.1"
+ cookie-signature "1.0.6"
+
cookie-signature@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
@@ -2798,6 +2897,10 @@ dom-serializer@0:
domelementtype "~1.1.1"
entities "~1.1.1"
+dom-walk@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
+
domain-browser@~1.1.0:
version "1.1.7"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc"
@@ -2992,6 +3095,21 @@ ember-cli-broccoli-sane-watcher@^2.0.4:
rsvp "^3.0.18"
sane "^2.4.1"
+ember-cli-cjs-transform@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/ember-cli-cjs-transform/-/ember-cli-cjs-transform-1.2.0.tgz#34a0d2667673caec0248f500a954f45668027e8b"
+ dependencies:
+ broccoli-debug "^0.6.4"
+ broccoli-plugin "^1.3.0"
+ ember-cli-babel "^6.6.0"
+ fs-extra "^5.0.0"
+ hash-for-dep "^1.2.3"
+ pkg-dir "^2.0.0"
+ rollup "^0.58.1"
+ rollup-plugin-commonjs "^9.1.0"
+ rollup-plugin-node-resolve "^3.3.0"
+ username "^3.0.0"
+
ember-cli-clipboard@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/ember-cli-clipboard/-/ember-cli-clipboard-0.9.0.tgz#c0cfce1a8a81ba1646e54bff9d41249b8bc507f7"
@@ -3270,6 +3388,14 @@ ember-cli-version-checker@^2.0.0, ember-cli-version-checker@^2.1.0:
resolve "^1.3.3"
semver "^5.3.0"
+ember-cli-yadda@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/ember-cli-yadda/-/ember-cli-yadda-0.4.0.tgz#0faaa3a4d945b3fc0974d0535e358c2897fdf170"
+ dependencies:
+ broccoli-persistent-filter "^1.4.3"
+ ember-cli-babel "^6.6.0"
+ yadda "*"
+
ember-cli@~2.18.2:
version "2.18.2"
resolved "https://registry.yarnpkg.com/ember-cli/-/ember-cli-2.18.2.tgz#bb15313a15139a85248a86d203643f918ba40f57"
@@ -3896,6 +4022,10 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+estree-walker@^0.5.1, estree-walker@^0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39"
+
esutils@^2.0.0, esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
@@ -3956,6 +4086,18 @@ execa@^0.10.0:
signal-exit "^3.0.0"
strip-eof "^1.0.0"
+execa@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
+ dependencies:
+ cross-spawn "^5.0.1"
+ get-stream "^3.0.0"
+ is-stream "^1.1.0"
+ npm-run-path "^2.0.0"
+ p-finally "^1.0.0"
+ signal-exit "^3.0.0"
+ strip-eof "^1.0.0"
+
execa@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da"
@@ -4024,7 +4166,7 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
dependencies:
homedir-polyfill "^1.0.1"
-express@^4.10.7, express@^4.12.3:
+express@^4.10.7, express@^4.12.3, express@^4.16.2:
version "4.16.3"
resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
dependencies:
@@ -4123,6 +4265,14 @@ eyes@0.1.x:
version "0.1.8"
resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
+fake-xml-http-request@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-2.0.0.tgz#41a92f0ca539477700cb1dafd2df251d55dac8ff"
+
+faker@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/faker/-/faker-4.1.0.tgz#1e45bbbecc6774b3c195fad2835109c6d748cc3f"
+
fast-deep-equal@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
@@ -4192,6 +4342,10 @@ file-entry-cache@^2.0.0:
flat-cache "^1.2.1"
object-assign "^4.0.1"
+file-saver@^1.3.3:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-1.3.8.tgz#e68a30c7cb044e2fb362b428469feb291c2e09d8"
+
filename-regex@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
@@ -4795,7 +4949,7 @@ hash-base@^3.0.0:
inherits "^2.0.1"
safe-buffer "^5.0.1"
-hash-for-dep@^1.0.2:
+hash-for-dep@^1.0.2, hash-for-dep@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/hash-for-dep/-/hash-for-dep-1.2.3.tgz#5ec69fca32c23523972d52acb5bb65ffc3664cab"
dependencies:
@@ -4960,6 +5114,10 @@ husky@^0.14.3:
normalize-path "^1.0.0"
strip-indent "^2.0.0"
+hyperhtml@^0.15.5:
+ version "0.15.10"
+ resolved "https://registry.yarnpkg.com/hyperhtml/-/hyperhtml-0.15.10.tgz#5e5f42393d4fc30cd803063fb88a5c9d97625e1c"
+
iconv-lite@0.4.19:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
@@ -5259,6 +5417,10 @@ is-integer@^1.0.4:
dependencies:
is-finite "^1.0.0"
+is-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
+
is-my-ip-valid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824"
@@ -5542,7 +5704,7 @@ js-yaml@0.3.x:
version "0.3.7"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-0.3.7.tgz#d739d8ee86461e54b354d6a7d7d1f2ad9a167f62"
-js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.6.1, js-yaml@^3.7.0, js-yaml@^3.9.0, js-yaml@^3.9.1:
+js-yaml@^3.10.0, js-yaml@^3.11.0, js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.6.1, js-yaml@^3.7.0, js-yaml@^3.8.4, js-yaml@^3.9.0, js-yaml@^3.9.1:
version "3.11.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef"
dependencies:
@@ -6251,6 +6413,12 @@ lru-cache@^4.0.1:
pseudomap "^1.0.2"
yallist "^2.1.2"
+magic-string@^0.22.4:
+ version "0.22.5"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e"
+ dependencies:
+ vlq "^0.2.2"
+
make-dir@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.2.0.tgz#6d6a49eead4aae296c53bbf3a1a008bd6c89469b"
@@ -6338,6 +6506,12 @@ media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+mem@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
+ dependencies:
+ mimic-fn "^1.0.0"
+
memory-streams@^0.1.0:
version "0.1.3"
resolved "https://registry.yarnpkg.com/memory-streams/-/memory-streams-0.1.3.tgz#d9b0017b4b87f1d92f55f2745c9caacb1dc93ceb"
@@ -6382,7 +6556,7 @@ methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
-micromatch@^2.1.5, micromatch@^2.3.7:
+micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7:
version "2.3.11"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
dependencies:
@@ -6443,6 +6617,12 @@ mimic-fn@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+min-document@^2.19.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
+ dependencies:
+ dom-walk "^0.1.0"
+
minimalistic-assert@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
@@ -6530,6 +6710,10 @@ morgan@^1.8.1:
on-finished "~2.3.0"
on-headers "~1.0.1"
+mousetrap@^1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.1.tgz#2a085f5c751294c75e7e81f6ec2545b29cbf42d9"
+
mout@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mout/-/mout-1.1.0.tgz#0b29d41e6a80fa9e2d4a5be9d602e1d9d02177f6"
@@ -6579,6 +6763,10 @@ natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+ncp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3"
+
negotiator@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
@@ -7151,6 +7339,12 @@ pinkie@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+pkg-dir@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
+ dependencies:
+ find-up "^2.1.0"
+
pluralize@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
@@ -7187,6 +7381,13 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+pretender@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/pretender/-/pretender-2.0.0.tgz#5adae189f1d5b25f86113f9225df25bed54f4072"
+ dependencies:
+ fake-xml-http-request "^2.0.0"
+ route-recognizer "^0.3.3"
+
prettier@^1.10.2:
version "1.12.0"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.0.tgz#d26fc5894b9230de97629b39cae225b503724ce8"
@@ -7749,12 +7950,52 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
-rollup@^0.41.4:
+rollup-plugin-commonjs@^9.1.0:
+ version "9.1.3"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.1.3.tgz#37bfbf341292ea14f512438a56df8f9ca3ba4d67"
+ dependencies:
+ estree-walker "^0.5.1"
+ magic-string "^0.22.4"
+ resolve "^1.5.0"
+ rollup-pluginutils "^2.0.1"
+
+rollup-plugin-memory@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-memory/-/rollup-plugin-memory-2.0.0.tgz#0a8ac6b57fa0e714f89a15c3ac82bc93f89c47c5"
+
+rollup-plugin-node-resolve@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.3.0.tgz#c26d110a36812cbefa7ce117cadcd3439aa1c713"
+ dependencies:
+ builtin-modules "^2.0.0"
+ is-module "^1.0.0"
+ resolve "^1.1.6"
+
+rollup-pluginutils@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.1.1.tgz#50289c94f8d7426647b14dc9fbb93643645a8d09"
+ dependencies:
+ estree-walker "^0.5.2"
+ micromatch "^2.3.11"
+ tosource "^1.0.0"
+
+rollup@^0.41.4, rollup@^0.41.6:
version "0.41.6"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.41.6.tgz#e0d05497877a398c104d816d2733a718a7a94e2a"
dependencies:
source-map-support "^0.4.0"
+rollup@^0.58.1:
+ version "0.58.2"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.58.2.tgz#2feddea8c0c022f3e74b35c48e3c21b3433803ce"
+ dependencies:
+ "@types/estree" "0.0.38"
+ "@types/node" "*"
+
+route-recognizer@^0.3.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/route-recognizer/-/route-recognizer-0.3.3.tgz#1d365e27fa6995e091675f7dc940a8c00353bd29"
+
rsvp@^3.0.14, rsvp@^3.0.16, rsvp@^3.0.17, rsvp@^3.0.18, rsvp@^3.0.21, rsvp@^3.0.6, rsvp@^3.1.0, rsvp@^3.2.1, rsvp@^3.3.3, rsvp@^3.5.0:
version "3.6.2"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
@@ -8684,6 +8925,10 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
+tosource@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/tosource/-/tosource-1.0.0.tgz#42d88dd116618bcf00d6106dd5446f3427902ff1"
+
tough-cookie@~2.3.0, tough-cookie@~2.3.3:
version "2.3.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
@@ -8765,7 +9010,7 @@ uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376"
-uglify-es@^3.1.3:
+uglify-es@^3.0.17, uglify-es@^3.1.3:
version "3.3.9"
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
dependencies:
@@ -8812,6 +9057,10 @@ underscore@>=1.8.3:
version "1.8.3"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
+unfetch@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-2.1.2.tgz#684fee4d8acdb135bdb26c0364c642fc326ca95b"
+
union-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"
@@ -8891,6 +9140,13 @@ username@^1.0.1:
dependencies:
meow "^3.4.0"
+username@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/username/-/username-3.0.0.tgz#b3dba982a72b4ce59d52f159fa1aeba266af5fc8"
+ dependencies:
+ execa "^0.7.0"
+ mem "^1.1.0"
+
util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -8941,6 +9197,10 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
+vlq@^0.2.2:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
+
vm-browserify@~0.0.1:
version "0.0.4"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
@@ -9085,6 +9345,10 @@ xdg-basedir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
+xhr2@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f"
+
xmldom@^0.1.19:
version "0.1.27"
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
@@ -9101,6 +9365,10 @@ y18n@^3.2.0, y18n@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+yadda@*:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/yadda/-/yadda-1.4.0.tgz#75b87196f4a864c4131705131fbbc2df3367b58f"
+
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
|