WIP: Feature/acceptance tests

This commit is contained in:
John Cowen 2018-05-11 13:47:21 +01:00
parent 47730f96ea
commit db1275f2eb
49 changed files with 1285 additions and 24 deletions

2
ui-v2/.gitignore vendored
View File

@ -8,3 +8,5 @@
/yarn-error.log
/testem.log
/public/consul-api-double

View File

@ -13,3 +13,18 @@ format:
yarn run format:js
.PHONY: server dist lint format
.DEFAULT_GOAL=all
.PHONY: deps test all build start
all: deps
deps: node_modules yarn.lock package.json
node_modules:
yarn
build:
yarn run build
start:
yarn run start
test:
yarn run test
test-view:
yarn run test:view

View File

@ -10,7 +10,7 @@
{{#ember-native-scrollable tagName='tbody' content-size=_contentSize scroll-left=_scrollLeft scroll-top=_scrollTop scrollChange=(action "scrollChange") clientSizeChange=(action "clientSizeChange")}}
<tr></tr>
{{~#each _cells as |cell|~}}
<tr style={{{cell.style}}} onclick={{action 'click'}}>
<tr data-test-tabular-row style={{{cell.style}}} onclick={{action 'click'}}>
{{#yield-slot 'row'}}{{yield cell.item cell.index}}{{/yield-slot}}
{{#if hasActions }}
<td class="actions">

View File

@ -1,6 +1,6 @@
<ul>
<ul data-test-node-healthchecks>
{{#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}}
</ul>

View File

@ -5,6 +5,7 @@
{{/if}}
{{#if (gt filtered.length 0)}}
{{#tabular-collection
data-test-services
items=filtered as |item index|
}}
{{#block-slot 'header'}}
@ -13,10 +14,10 @@
<th>Tags</th>
{{/block-slot}}
{{#block-slot 'row'}}
<td>
<td data-test-service-name="{{item.Service}}">
<a href={{href-to 'dc.services.show' item.Service }}>{{item.Service}}</a>
</td>
<td>
<td data-test-service-port="{{item.Port}}" class="port">
{{item.Port}}
</td>
<td>

View File

@ -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;
};

View File

@ -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": "cp -R ./node_modules/@johncowen/consul-api-double ./public/consul-api-double"
},
"lint-staged": {
"{app,config,lib,server,tests}/**/*.js": [
@ -26,11 +28,17 @@
"prettier --write",
"git add"
]
},
"dependencies": {
},
"devDependencies": {
"@johncowen/ember-cli-api-double": "johncowen/ember-cli-api-double#master",
"@johncowen/consul-api-double": "johncowen/consul-api-double#master",
"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 +48,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 +64,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",

View File

@ -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
And I see managementIsSelected on the filter
And I see 1 [Model] model
When I click client on the filter
And I see clientIsSelected 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: Anonymous Token
---
And I see 1 [Model] model with the name "Anonymous Token"
Where:
-------------------------------------------------
| Model | Page | Url |
| acl | acls | /dc-1/acls |
-------------------------------------------------

View File

@ -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 |
-------------------------------------------------

View File

@ -0,0 +1,27 @@
@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 pause for 3000
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 |
----------------------------------------------------------------

View File

@ -0,0 +1,38 @@
@setupApplicationTest
Feature: 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 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

View File

@ -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

View File

@ -0,0 +1,32 @@
@setupApplicationTest
Feature: 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 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: Rules can be edited/updated
# Then ok
# @ignore
# Scenario: The feedback dialog says success or failure
# Then ok

View File

@ -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 |
-------------------------------------------------

View File

@ -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

View File

@ -0,0 +1,17 @@
@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
And then pause for 3000

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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/key-0 |
| acl | acls | /dc-1/acls/anonymous |
---------------------------------------------------
@ignore
Scenario: Clicking a kv in the kvs listing
Then ok

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -0,0 +1,11 @@
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);
// });
}

View File

@ -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);
});
}

View File

@ -0,0 +1,2 @@
import steps from 'consul-ui/tests/steps';
export default steps;

View File

@ -0,0 +1,4 @@
import getAPI from '@johncowen/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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 };

View File

@ -0,0 +1,2 @@
import yadda from 'npm:yadda';
export default yadda;

View File

@ -0,0 +1,56 @@
// 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;
}
export function visitable(path, encoder = encodeURIComponent) {
return {
isDescriptor: true,
value(dynamicSegmentsAndQueryParams = {}) {
let executionContext = getExecutionContext(this);
return executionContext.runAsync(context => {
let params = assign({}, dynamicSegmentsAndQueryParams);
let fullPath = fillInDynamicSegments(path, params, encoder);
fullPath = appendQueryParams(fullPath, params);
return context.visit(fullPath);
});
},
};
}

View File

@ -1,7 +1,8 @@
import { create, visitable, fillable, clickable } from 'ember-cli-page-object';
import { create, visitable, clickable, triggerable } from 'ember-cli-page-object';
export default create({
visit: visitable('/:dc/acls/:acl'),
fillIn: fillable('input, textarea, [contenteditable]'),
// fillIn: fillable('input, textarea, [contenteditable]'),
name: triggerable('keypress', '[name="name"]'),
submit: clickable('[type=submit]'),
});

View File

@ -1,7 +1,9 @@
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]'),
visit: visitable('/:dc/kv/:kv/edit', str => str),
// fillIn: fillable('input, textarea, [contenteditable]'),
// name: triggerable('keypress', '[name="additional"]'),
submit: clickable('[type=submit]'),
});

View File

@ -1,6 +1,8 @@
import { create, visitable, collection } from 'ember-cli-page-object';
import { create, visitable, collection, attribute } from 'ember-cli-page-object';
export default create({
visit: visitable('/:dc/kv'),
kvs: collection('[data-test-kv]'),
kvs: collection('[data-test-kv]', {
name: attribute('data-test-kv'),
}),
});

View File

@ -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'),
}),
});

211
ui-v2/tests/steps.js Normal file
View File

@ -0,0 +1,211 @@
/* eslint no-console: "off" */
import yadda from './helpers/yadda';
import { currentURL, click, triggerKeyEvent } from '@ember/test-helpers';
import getDictionary from '@johncowen/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];
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
if (typeof currentPage[component].objectAt === 'function') {
return currentPage[component].objectAt(0)[prop]();
} else {
return currentPage[component][prop]();
}
})
.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} but was ${request.method}`
);
assert.equal(
request.url,
url,
`Expected the request url to be ${url} but 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]} but ${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} but was ${request.method}`
);
assert.equal(
request.url,
url,
`Expected the request url to be ${url} but was ${request.url}`
);
const body = request.requestBody;
assert.equal(
body,
data,
`Expected the request body to be ${body} but was ${request.requestBody}`
);
})
.then('the url should be $url', function(url) {
const current = currentURL();
assert.equal(current, url, `Expected the url to be ${url} but 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 but 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}" but saw ${len}`
);
})
.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);
})
);
}

View File

@ -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"
"@johncowen/api-double@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@johncowen/api-double/-/api-double-1.1.0.tgz#748a87134cd6a0a4e136d262bebbf1c444d6d291"
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"
"@johncowen/consul-api-double@johncowen/consul-api-double#master":
version "0.1.0"
resolved "https://codeload.github.com/johncowen/consul-api-double/tar.gz/33a81ea3ee17da91cef964ecfbe0659009ce2ca2"
"@johncowen/ember-cli-api-double@johncowen/ember-cli-api-double#master":
version "1.0.0"
resolved "https://codeload.github.com/johncowen/ember-cli-api-double/tar.gz/1946b56945e2fc413311a5d782f7748fab0d500c"
dependencies:
"@johncowen/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"