diff --git a/.eslintrc.test.config.js b/.eslintrc.test.config.js index 84349f64b..f41ff4689 100644 --- a/.eslintrc.test.config.js +++ b/.eslintrc.test.config.js @@ -23,7 +23,8 @@ module.exports = { "jest/no-focused-tests": "error", "jest/no-identical-title": "error", "jest/valid-expect": "error", - "max-len": ["error", 180, 4, { "ignoreComments": true }] + "max-len": ["error", 180, 4, { "ignoreComments": true }], + "max-lines": ["error", {"max": 800, "skipComments": true}], }, "env": { "jest/globals": true diff --git a/.gitignore b/.gitignore index 38af4ed56..ccaa7d817 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ gen-docs **/.DS_Store .vscode cypress/videos/ +cypress/screenshots/ diff --git a/.travis.yml b/.travis.yml index fb52b5a30..3e44cb249 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: node_js node_js: - "8.9.0" install: - - yarn install + - npm install before_script: - npm start -- --silent & script: diff --git a/cypress.json b/cypress.json index 0967ef424..dfca4140a 100644 --- a/cypress.json +++ b/cypress.json @@ -1 +1,3 @@ -{} +{ + "videoRecording": false +} diff --git a/cypress/common/page-objects/node.po.js b/cypress/common/page-objects/node.po.js index f81b55b4d..f54cb7c9f 100644 --- a/cypress/common/page-objects/node.po.js +++ b/cypress/common/page-objects/node.po.js @@ -1,3 +1,5 @@ +/*global cy*/ + /** * Page Object for interacting with Node component. * @param {string} id the id of the node. diff --git a/cypress/common/page-objects/sandbox.po.js b/cypress/common/page-objects/sandbox.po.js index fe79cea22..d26c9dc03 100644 --- a/cypress/common/page-objects/sandbox.po.js +++ b/cypress/common/page-objects/sandbox.po.js @@ -1,19 +1,32 @@ +/*global cy*/ + /** * Page Object for interacting with sandbox interface. * @returns {undefined} */ function SandboxPO () { // whitelist checkbox inputs - this.checkboxes = [ 'node.renderLabel' ]; - + this.checkboxes = ['node.renderLabel', 'staticGraph']; + // actions this.playGraph = () => cy.get('.container__graph > :nth-child(1) > :nth-child(2)').click(); this.pauseGraph = () => cy.get('.container__graph > :nth-child(1) > :nth-child(3)').click(); + this.addNode = () => cy.get('.container__graph > :nth-child(1) > :nth-child(5)').click(); + this.removeNode = () => cy.get('.container__graph > :nth-child(1) > :nth-child(6)').click(); + this.clickJsonTreeNodes = () => { + cy.get('.container__graph-data').contains('root').scrollIntoView(); + cy.get('.container__graph-data').contains('nodes').click(); + }; + // must be collapsed + this.clickJsonTreeFirstNode = () => cy.get(':nth-child(2) > .rejt-not-collapsed > .rejt-not-collapsed-list > :nth-child(1) > .rejt-collapsed > .rejt-collapsed-text').click(); + this.addJsonTreeFirstNodeProp = () => cy.get(':nth-child(2) > :nth-child(1) > .rejt-not-collapsed > :nth-child(4) > .rejt-plus-menu').click(); + this.deleteJsonTreeFirstNodeProp = () => cy.get('.rejt-not-collapsed-list > :nth-child(2) > .rejt-minus-menu').click(); // element getters this.getFieldInput = (field) => this.checkboxes.includes(field) ? cy.contains(field).children('input') : cy.contains(field).siblings('.form-control'); + this.getGraphNumbers = () => cy.get('.container__graph-info'); } module.exports = SandboxPO; \ No newline at end of file diff --git a/cypress/integration/graph.e2e.js b/cypress/integration/graph.e2e.js new file mode 100644 index 000000000..e55b6d3aa --- /dev/null +++ b/cypress/integration/graph.e2e.js @@ -0,0 +1,105 @@ +/*global cy*/ +const SANDBOX_URL = Cypress.env('SANDBOX_URL'); + +const NodePO = require('../common/page-objects/node.po'); +const SandboxPO = require('../common/page-objects/sandbox.po'); +let nodes = require('./../../sandbox/data').nodes.map(({id}) => id); + +describe('[rd3g-graph] graph tests', function () { + before(function () { + this.sandboxPO = new SandboxPO(); + // visit sandbox + cy.visit(SANDBOX_URL); + // sleep 2 seconds + cy.wait(2000); + // pause the graph + this.sandboxPO.pauseGraph(); + }); + + describe('when data is changed', function () { + describe('and we change nodes props', function () { + beforeEach(function () { + // expand nodes + this.sandboxPO.clickJsonTreeNodes(); + // expand 1st node + this.sandboxPO.clickJsonTreeFirstNode(); + }); + + afterEach(function () { + this.sandboxPO.clickJsonTreeNodes(); + }); + + it('nodes props modifications should be reflected in the graph', function () { + // click (+) add prop to 1st node + this.sandboxPO.addJsonTreeFirstNodeProp(); + + // prop name be color + cy.get('[placeholder="Key"]') + .clear() + .type('color'); + + // prop value be red and press ENTER + cy.get('[placeholder="Value"]') + .clear() + .type('red{enter}'); + + const nodePO = new NodePO(nodes[0]); + + nodePO.getColor().should('eq', 'red'); + + // delete created prop + this.sandboxPO.deleteJsonTreeFirstNodeProp(); + + nodePO.getColor().should('eq', '#d3d3d3'); + }); + + describe('and staticGraph is toggled on', function () { + beforeEach(function () { + cy.contains('staticGraph').scrollIntoView(); + this.sandboxPO.getFieldInput('staticGraph').click(); + }); + + it('nodes props modifications should be reflected in the graph', function () { + cy.get('text').should('have.length', 14); + + this.sandboxPO.addNode(); + this.sandboxPO.addNode(); + this.sandboxPO.addNode(); + this.sandboxPO.addNode(); + + cy.get('text').should('have.length', 18); + + // click (+) add prop to 1st node + this.sandboxPO.addJsonTreeFirstNodeProp(); + // prop name be color + cy.get('[placeholder="Key"]') + .clear() + .type('color'); + // prop value be red and press ENTER + cy.get('[placeholder="Value"]') + .clear() + .type('red{enter}'); + + const nodePO = new NodePO(nodes[0]); + + nodePO.getColor().should('eq', 'red'); + + // delete created prop + this.sandboxPO.deleteJsonTreeFirstNodeProp(); + + nodePO.getColor().should('eq', '#d3d3d3'); + + this.sandboxPO.removeNode(); + + cy.get('text').should('have.length', 17); + + this.sandboxPO.removeNode(); + this.sandboxPO.removeNode(); + this.sandboxPO.removeNode(); + + cy.get('text').should('have.length', 14); + }); + }); + }); + }); +}); \ No newline at end of file diff --git a/cypress/integration/node.e2e.js b/cypress/integration/node.e2e.js index c4a94f25d..105782379 100644 --- a/cypress/integration/node.e2e.js +++ b/cypress/integration/node.e2e.js @@ -1,6 +1,8 @@ +/*global cy*/ +const SANDBOX_URL = Cypress.env('SANDBOX_URL'); + const NodePO = require('../common/page-objects/node.po'); const SandboxPO = require('../common/page-objects/sandbox.po'); -const SANDBOX_URL = Cypress.env('SANDBOX_URL'); let nodes = require('./../../sandbox/data').nodes.map(({id}) => id); describe('[rd3g-node] node tests', function () { diff --git a/package-lock.json b/package-lock.json index a15cb75c2..d537936df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2873,9 +2873,9 @@ } }, "cypress": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-1.4.1.tgz", - "integrity": "sha1-YvQHSgDm8S4t/jiKf06BaknOsD8=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-2.0.1.tgz", + "integrity": "sha512-6LIrMzvPh/v95JXUclJpCNumf4filJpXCj79kPazh4ohyGXIsUI9nZ7CsFEU6dieX46N1tGORMr93ruVXzhoFw==", "dev": true, "requires": { "@cypress/listr-verbose-renderer": "0.4.1", @@ -9987,6 +9987,12 @@ } } }, + "mousetrap": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.1.tgz", + "integrity": "sha1-KghfXHUSlMdefoH27CVFspy/Qtk=", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -11847,6 +11853,28 @@ "prop-types": "15.6.0" } }, + "react-editable-json-tree": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/react-editable-json-tree/-/react-editable-json-tree-2.1.0.tgz", + "integrity": "sha512-4I0rQIBs5S8FLEVjZrCUJAk2+9t/dkmZLQVB2Dt+SombQph/8GZ97yhzV0u8iIU49Use9cWCReyUfZ2oicjOYw==", + "dev": true, + "requires": { + "prop-types": "15.6.0", + "react-hotkeys": "0.10.0" + } + }, + "react-hotkeys": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/react-hotkeys/-/react-hotkeys-0.10.0.tgz", + "integrity": "sha1-0eeL1j8W1ttY1VDTPI6wcfNdlPs=", + "dev": true, + "requires": { + "create-react-class": "15.6.2", + "lodash": "4.17.4", + "mousetrap": "1.6.1", + "prop-types": "15.6.0" + } + }, "react-jsonschema-form": { "version": "0.50.1", "resolved": "https://registry.npmjs.org/react-jsonschema-form/-/react-jsonschema-form-0.50.1.tgz", diff --git a/package.json b/package.json index cb68c1687..89ab55cae 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "babel-preset-react": "6.24.1", "babel-preset-stage-0": "6.24.1", "css-loader": "0.28.7", - "cypress": "1.4.1", + "cypress": "2.0.1", "documentation": "5.3.2", "eslint": "3.18.0", "eslint-config-recommended": "1.5.0", @@ -59,6 +59,7 @@ "npm-run-all": "4.1.1", "react-addons-test-utils": "15.6.0", "react-dom": "15.6.1", + "react-editable-json-tree": "2.1.0", "react-jsonschema-form": "0.50.1", "react-router-dom": "4.2.2", "react-test-renderer": "15.6.1", diff --git a/sandbox/Sandbox.jsx b/sandbox/Sandbox.jsx index 3478742b7..5a174812f 100644 --- a/sandbox/Sandbox.jsx +++ b/sandbox/Sandbox.jsx @@ -1,3 +1,5 @@ +/*global console*/ +/*eslint require-jsdoc: 0, valid-jsdoc: 0, no-console: 0*/ import React from 'react'; import Form from 'react-jsonschema-form'; @@ -9,6 +11,7 @@ import { Graph } from '../src'; import data from './data'; import Utils from './utils'; import ReactD3GraphUtils from '../src/utils'; +import { JsonTree } from 'react-editable-json-tree'; /** * This is a sample integration of react-d3-graph, in this particular case all the rd3g config properties @@ -49,9 +52,11 @@ export default class Sandbox extends React.Component { onMouseOutNode = (id) => console.info(`Do something when mouse is out of node (${id})`); - onMouseOverLink = (source, target) => console.info(`Do something when mouse is over link between ${source} and ${target}`); + onMouseOverLink = (source, target) => + console.info(`Do something when mouse is over link between ${source} and ${target}`); - onMouseOutLink = (source, target) => console.info(`Do something when mouse is out of link between ${source} and ${target}`); + onMouseOutLink = (source, target) => + console.info(`Do something when mouse is out of link between ${source} and ${target}`); /** * Sets on/off fullscreen visualization mode. @@ -123,13 +128,14 @@ export default class Sandbox extends React.Component { onClickRemoveNode = () => { if (this.state.data.nodes && this.state.data.nodes.length) { const id = this.state.data.nodes[0].id; + this.state.data.nodes.splice(0, 1); const links = this.state.data.links.filter(l => l.source !== id && l.target !== id); const data = { nodes: this.state.data.nodes, links }; this.setState({ data }); } else { - alert('No more nodes to remove!'); + window.alert('No more nodes to remove!'); } } @@ -137,12 +143,12 @@ export default class Sandbox extends React.Component { let config = {}; let schemaPropsValues = {}; - for(let k of Object.keys(data.formData)) { + for (let k of Object.keys(data.formData)) { // Set value mapping correctly for config object of react-d3-graph Utils.setValue(config, k, data.formData[k]); // Set new values for schema of jsonform schemaPropsValues[k] = {}; - schemaPropsValues[k]['default'] = data.formData[k] + schemaPropsValues[k]['default'] = data.formData[k]; } return {config, schemaPropsValues}; @@ -162,11 +168,9 @@ export default class Sandbox extends React.Component { * Generate graph configuration file ready to use! */ onSubmit = (data) => { - const {config, schemaPropsValues} = this._buildGraphConfig(data); + const { config } = this._buildGraphConfig(data); - this.setState({ - generatedConfig: config - }); + this.setState({ generatedConfig: config }); } onClickSubmit = () => { @@ -199,14 +203,21 @@ export default class Sandbox extends React.Component { * @return {Object} the graph where now nodes containing (x,y) coords. */ decorateGraphNodesWithInitialPositioning = (nodes) => { - return nodes.map(n => ({ - id: n.id, - x: Math.floor(Math.random() * 500), - y: Math.floor(Math.random() * 500), - symbolType: n.symbolType || 'circle' - })); + return nodes.map(n => ( + Object.assign({}, n, { + x: n.x || Math.floor(Math.random() * 500), + y: n.y || Math.floor(Math.random() * 500) + }) + )); } + /** + * Update graph data each time an update is triggered + * by JsonTree + * @param {Object} data update graph data (nodes and links) + */ + onGraphDataUpdate = (data) => this.setState({ data }); + /** * Build common piece of the interface that contains some interactions such as * fullscreen, play/pause, + and - buttons. @@ -218,7 +229,8 @@ export default class Sandbox extends React.Component { const fullscreen = this.state.fullscreen ? () - : (); + : (); return (
@@ -226,8 +238,8 @@ export default class Sandbox extends React.Component { - - + + Nodes: {this.state.data.nodes.length} | Links: {this.state.data.links.length} @@ -238,12 +250,10 @@ export default class Sandbox extends React.Component { render() { // This does not happens in this sandbox scenario running time, but if we set staticGraph config // to true in the constructor we will provide nodes with initial positions - const data = this.state.config.staticGraph ? - { + const data = { nodes: this.decorateGraphNodesWithInitialPositioning(this.state.data.nodes), links: this.state.data.links - } - : this.state.data; + }; const graphProps = { id: 'graph', @@ -302,8 +312,10 @@ export default class Sandbox extends React.Component {
-

Initial Graph Data

- +

Graph Data (editable)

+
+ +
); @@ -312,7 +324,7 @@ export default class Sandbox extends React.Component { } class JSONContainer extends React.Component { - shouldComponentUpdate(nextProps, nextState) { + shouldComponentUpdate(nextProps) { return !this.props.staticData && !ReactD3GraphUtils.isDeepEqual(nextProps.data, this.props.data); } diff --git a/sandbox/styles.css b/sandbox/styles.css index d6e9d7adf..bd6edced6 100644 --- a/sandbox/styles.css +++ b/sandbox/styles.css @@ -15,7 +15,7 @@ } .container__graph { - grid-column: 1 / 5; + grid-column: 1 / 4; grid-row: 1 / 2; border: 1px solid black; } @@ -32,26 +32,30 @@ max-width: 800px; max-height: 400px; border: 1px dotted gray; - margin-left: 80px; + margin-left: 20px; margin-top: 4px; + z-index: 1; } .container__graph-data { grid-column: 1 / 2; grid-row: 2 / 3; margin-bottom: 4px; + z-index: 2; } .container__graph-config { grid-column: 2 / 3; grid-row: 2 / 3; margin-bottom: 4px; + z-index: 2; } .container__form { grid-column: 5/ 6; grid-row: 1 / 4; min-width: 400px; + z-index: 3; } .cross-icon { diff --git a/src/components/graph/graph.helper.js b/src/components/graph/graph.helper.js index 05492ca10..7a1f7fdca 100644 --- a/src/components/graph/graph.helper.js +++ b/src/components/graph/graph.helper.js @@ -30,6 +30,8 @@ import ERRORS from '../../err'; import utils from '../../utils'; +const NODE_PROPS_WHITELIST = ['id', 'highlighted', 'x', 'y', 'index', 'vy', 'vx']; + /** * Create d3 forceSimulation to be applied on the graph.
* {@link https://github.com/d3/d3-force#forceSimulation|d3-force#forceSimulation}
@@ -125,8 +127,8 @@ function _initializeNodes(graphNodes) { node.highlighted = false; - if (!node.hasOwnProperty('x')) { node['x'] = 0; } - if (!node.hasOwnProperty('y')) { node['y'] = 0; } + if (!node.hasOwnProperty('x')) { node.x = 0; } + if (!node.hasOwnProperty('y')) { node.y = 0; } nodes[node.id.toString()] = node; } @@ -312,10 +314,16 @@ function initializeGraphState({data, id, config}, state) { _validateGraphData(data); + const nodesInputSnapshot = data.nodes.map(n => Object.assign({}, n)); + const linksInputSnapshot = data.links.map(l => Object.assign({}, l)); + if (state && state.nodes && state.links) { // absorb existent positioning graph = { - nodes: data.nodes.map(n => Object.assign({}, n, state.nodes[n.id])), + nodes: data.nodes.map(n => state.nodes[n.id] + ? Object.assign({}, n, utils.pick(state.nodes[n.id], NODE_PROPS_WHITELIST)) + : Object.assign({}, n) + ), links: {} }; } else { @@ -339,13 +347,15 @@ function initializeGraphState({data, id, config}, state) { config: newConfig, links, d3Links, + linksInputSnapshot, nodes, d3Nodes, + nodesInputSnapshot, highlightedNode: '', simulation, newGraphElements: false, configUpdated: false, - transform: 1 + transform: 1, }; } diff --git a/src/components/graph/index.jsx b/src/components/graph/index.jsx index 2f7921809..078217116 100644 --- a/src/components/graph/index.jsx +++ b/src/components/graph/index.jsx @@ -182,9 +182,10 @@ export default class Graph extends React.Component { /** * The tick function simply calls React set state in order to update component and render nodes * along time as d3 calculates new node positioning. + * @param {Object} state - new state to pass on. * @returns {undefined} */ - _tick = () => this.setState(this.state || {}); + _tick = (state={}) => this.setState(state); /** * Configures zoom upon graph with default or user provided values.
@@ -266,7 +267,7 @@ export default class Graph extends React.Component { * {@link https://github.com/d3/d3-force#simulation_stop} * @returns {undefined} */ - pauseSimulation = () => !this.state.config.staticGraph && this.state.simulation.stop(); + pauseSimulation = () => this.state.simulation.stop(); /** * This method resets all nodes fixed positions by deleting the properties fx (fixed x) @@ -309,14 +310,14 @@ export default class Graph extends React.Component { } componentWillReceiveProps(nextProps) { - const newGraphElements = nextProps.data.nodes.length !== this.state.d3Nodes.length - || nextProps.data.links.length !== this.state.d3Links.length; - - if (newGraphElements && nextProps.config.staticGraph) { - utils.throwErr(this.constructor.name, ERRORS.STATIC_GRAPH_DATA_UPDATE); - } - - const configUpdated = !utils.isDeepEqual(nextProps.config, this.state.config); + const newGraphElements = nextProps.data.nodes.length !== this.state.nodesInputSnapshot.length + || nextProps.data.links.length !== this.state.linksInputSnapshot.length + || !utils.isDeepEqual(nextProps.data, { + nodes: this.state.nodesInputSnapshot, + links: this.state.linksInputSnapshot, + }); + const configUpdated = !utils.isObjectEmpty(nextProps.config) + && !utils.isDeepEqual(nextProps.config, this.state.config); const state = newGraphElements ? graphHelper.initializeGraphState(nextProps, this.state) : this.state; const config = configUpdated ? utils.merge(DEFAULT_CONFIG, nextProps.config || {}) : this.state.config; @@ -336,17 +337,17 @@ export default class Graph extends React.Component { componentDidUpdate() { // if the property staticGraph was activated we want to stop possible ongoing simulation - this.state.config.staticGraph && this.state.simulation.stop(); + this.state.config.staticGraph && this.pauseSimulation(); if (!this.state.config.staticGraph && this.state.newGraphElements) { this._graphForcesConfig(); this.restartSimulation(); - this.state.newGraphElements = false; + this.setState({ newGraphElements: false }); } if (this.state.configUpdated) { this._zoomConfig(); - this.state.configUpdated = false; + this.setState({ configUpdated: false }); } } @@ -360,7 +361,7 @@ export default class Graph extends React.Component { } componentWillUnmount() { - this.state.simulation.stop(); + this.pauseSimulation(); } render() { diff --git a/src/err.js b/src/err.js index 1bf9d881e..3f747c55e 100644 --- a/src/err.js +++ b/src/err.js @@ -1,7 +1,6 @@ /*eslint max-len: ["error", 200]*/ export default { GRAPH_NO_ID_PROP: "id prop not defined! id property is mandatory and it should be unique.", - STATIC_GRAPH_DATA_UPDATE: "a static graph cannot receive new data (nodes or links). Make sure config.staticGraph is set to true if you want to update graph data", INVALID_LINKS: "you provided a invalid links data structure. Links source and target attributes must point to an existent node", INSUFFICIENT_DATA: "you have not provided enough data for react-d3-graph to render something. You need to provide at least one node" }; diff --git a/src/utils.js b/src/utils.js index 875bb20f4..f282a0296 100644 --- a/src/utils.js +++ b/src/utils.js @@ -12,7 +12,7 @@ const MAX_DEPTH = 20; /** * Checks whether a certain object property is from object type and is a non empty object. * @param {Object} o - the object. - * @param {number|string} k - the object property. + * @param {string} k - the object property. * @returns {boolean} returns true if o[k] is an non empty object. * @memberof utils */ @@ -39,7 +39,14 @@ function isDeepEqual(o1, o2, _depth=0) { return false; } - for (let k of Object.keys(o1)) { + const o1Keys = Object.keys(o1); + const o2Keys = Object.keys(o2); + + if (o1Keys.length !== o2Keys.length) { + return false; + } + + for (let k of o1Keys) { const nestedO = _isPropertyNestedObject(o1, k) && _isPropertyNestedObject(o2, k); if (nestedO && _depth < MAX_DEPTH) { @@ -103,6 +110,23 @@ function merge(o1={}, o2={}, _depth=0) { return o; } +/** + * Create new object from the inputted one only with the props passed + * in the props list. + * @param {Object} o - the object to pick props from. + * @param {Array.} props - list of props that we want to pick from o. + * @returns {Object} the object resultant from the picking operation. + */ +function pick(o, props) { + return Object.keys(o).reduce((acc, k) => { + if (o.hasOwnProperty(k) && props.includes(k)) { + acc[k] = o[k]; + } + + return acc; + }, {}); +} + /** * Helper function for customized error logging. * @param {string} component - the name of the component where the error is to be thrown. @@ -120,5 +144,6 @@ export default { isDeepEqual, isObjectEmpty, merge, + pick, throwErr }; diff --git a/test/component/graph/graph.helper.test.js b/test/component/graph/graph.helper.test.js index d7cf49b2d..25cc1cba0 100644 --- a/test/component/graph/graph.helper.test.js +++ b/test/component/graph/graph.helper.test.js @@ -2,7 +2,6 @@ import * as graphHelper from '../../../src/components/graph/graph.helper'; import config from '../../../src/components/graph/config'; -jest.mock('../../../src/utils'); import utils from '../../../src/utils'; jest.mock('d3-force'); @@ -14,6 +13,13 @@ import { } from 'd3-force'; describe('Graph Helper', () => { + beforeAll(() => { + utils.isDeepEqual = jest.fn(); + utils.isObjectEmpty = jest.fn(); + utils.merge = jest.fn(); + utils.throwErr = jest.fn(); + }); + describe('#buildNodeProps', () => { let that = {}; @@ -334,7 +340,21 @@ describe('Graph Helper', () => { simulation: { force: forceStub }, - transform: 1 + transform: 1, + nodesInputSnapshot: [{ + id: 'A' + }, { + id: 'B' + }, { + id: 'C' + }], + linksInputSnapshot: [{ + source: 'A', + target: 'B' + }, { + source: 'C', + target: 'A' + }] } ); }); diff --git a/test/utils.test.js b/test/utils.test.js index 113d249de..013157d4d 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -63,8 +63,8 @@ describe('Utils', () => { beforeEach(() => { that.o1 = { a:1, - b:{ - c:{ d: false, e: 'test', f: 12 }, + b: { + c: { d: false, e: 'test', f: 12 }, g: 'test', h: undefined, i: {}, @@ -74,7 +74,8 @@ describe('Utils', () => { m: { n: { o: 1 - } + }, + p: [ { x: 1 }, { y: 2 } ] } } } @@ -82,8 +83,8 @@ describe('Utils', () => { that.o2 = { a:1, - b:{ - c:{ d: false, e: 'test', f: 12 }, + b: { + c: { d: false, e: 'test', f: 12 }, g: 'test', h: undefined, i: {}, @@ -93,7 +94,8 @@ describe('Utils', () => { m: { n: { o: 1 - } + }, + p: [ { x: 1 }, { y: 2 } ] } } } @@ -178,6 +180,40 @@ describe('Utils', () => { that.o2.b.g = [1, 2, 3]; expect(utils.isDeepEqual(that.o1, that.o2)).toEqual(false); }); + + test('should return false when o1.a.b.c and o2.a.b.c are objects with different number of properties', () => { + that.o2.b.c = { d: false, e: 'test', f: 12, ff: false }; + expect(utils.isDeepEqual(that.o1, that.o2)).toEqual(false); + }); + + test('should return false when o1.b.j.m.p array\'s first object has different x value ', () => { + that.o1.b.j.m.p[0].x = 9000; + expect(utils.isDeepEqual(that.o1, that.o2)).toEqual(false); + }); + }); + + describe('#pick', () => { + let that = {}; + + beforeEach(() => { + that.o = { + a: 1, + b: { + j: { + k: null, + l: 'test', + } + }, + c: 'test', + f: 0 + }; + }); + + test('should pick given props and return expected object', () => { + const result = utils.pick(that.o, ['a', 'f', 'not a o prop']); + + expect(result).toEqual({ a: 1, f: 0 }); + }); }); describe('#throwErr', () => { diff --git a/yarn.lock b/yarn.lock index 184e023e6..5d4cd4c49 100644 --- a/yarn.lock +++ b/yarn.lock @@ -74,8 +74,8 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.44.tgz#1d4a798e53f35212fd5ad4d04050620171cd5b5e" "@types/node@*": - version "9.4.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.5.tgz#d2a90c634208173d1b1a0a6ba9f1df3de62edcf5" + version "9.4.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.6.tgz#d8176d864ee48753d053783e4e463aec86b8d82e" "@types/sinon-chai@2.7.29": version "2.7.29" @@ -239,8 +239,8 @@ are-we-there-yet@~1.1.2: readable-stream "^2.0.6" argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" dependencies: sprintf-js "~1.0.2" @@ -324,8 +324,8 @@ asap@~2.0.3: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" asn1.js@^4.0.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a" + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -1258,12 +1258,12 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" base62@^1.1.0: - version "1.2.5" - resolved "https://registry.yarnpkg.com/base62/-/base62-1.2.5.tgz#f59b629268aadafa2887667546b1fe3e15565507" + version "1.2.7" + resolved "https://registry.yarnpkg.com/base62/-/base62-1.2.7.tgz#5c01aad73c0124f9535cff1bdb9c4e6ccf838cfb" base64-js@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" + version "1.2.3" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.3.tgz#fb13668233d9614cf5fb4bce95a9ba4096cdf801" base@^0.11.1: version "0.11.2" @@ -1386,8 +1386,8 @@ braces@^1.8.2: repeat-element "^1.1.2" braces@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.0.tgz#a46941cb5fb492156b3d6a656e06c35364e3e66e" + version "2.3.1" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb" dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -1395,6 +1395,7 @@ braces@^2.3.0: extend-shallow "^2.0.1" fill-range "^4.0.0" isobject "^3.0.1" + kind-of "^6.0.2" repeat-element "^1.1.2" snapdragon "^0.8.1" snapdragon-node "^2.0.1" @@ -1580,12 +1581,12 @@ caniuse-api@^1.5.2: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000808" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000808.tgz#30dfd83009d5704f02dffb37725068ed12a366bb" + version "1.0.30000809" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000809.tgz#b0b88434a598f40b546d46a4dbd839b0ff798f4d" caniuse-lite@^1.0.30000792: - version "1.0.30000808" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000808.tgz#7d759b5518529ea08b6705a19e70dbf401628ffc" + version "1.0.30000809" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000809.tgz#1e12c1344b8f74d56737ee2614bcedb648943479" caseless@~0.12.0: version "0.12.0" @@ -1620,7 +1621,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796" dependencies: @@ -1829,9 +1830,9 @@ colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: delayed-stream "~1.0.0" @@ -1878,10 +1879,10 @@ component-emitter@^1.2.1: resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" compressible@~2.0.11: - version "2.0.12" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66" + version "2.0.13" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9" dependencies: - mime-db ">= 1.30.0 < 2" + mime-db ">= 1.33.0 < 2" compression@^1.5.2: version "1.7.1" @@ -2012,7 +2013,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -create-react-class@^15.6.0: +create-react-class@^15.5.2, create-react-class@^15.6.0: version "15.6.3" resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" dependencies: @@ -2158,9 +2159,9 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": dependencies: cssom "0.3.x" -cypress@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-1.4.1.tgz#62f4074a00e6f12e2dfe388a7f4e816a49ceb03f" +cypress@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-2.0.1.tgz#cbb62e7c2ff7e646aab5ab0570db07ceaecf3d4e" dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.1.3" @@ -2551,6 +2552,13 @@ define-property@^1.0.0: dependencies: is-descriptor "^1.0.0" +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -2903,8 +2911,8 @@ envify@^3.0.0: through "~2.3.4" errno@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026" + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" dependencies: prr "~1.0.1" @@ -2940,8 +2948,8 @@ es-to-primitive@^1.1.1: is-symbol "^1.0.1" es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.38" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.38.tgz#fa7d40d65bbc9bb8a67e1d3f9cc656a00530eed3" + version "0.10.39" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.39.tgz#fca21b67559277ca4ac1a1ed7048b107b6f76d87" dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" @@ -3420,7 +3428,7 @@ extend-shallow@^2.0.1: dependencies: is-extendable "^0.1.0" -extend-shallow@^3.0.0: +extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" dependencies: @@ -3666,11 +3674,11 @@ form-data@~2.1.1: mime-types "^2.1.12" form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" dependencies: asynckit "^0.4.0" - combined-stream "^1.0.5" + combined-stream "1.0.6" mime-types "^2.1.12" forwarded@~0.1.2: @@ -4108,12 +4116,12 @@ hoek@2.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + version "4.2.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" hoist-non-react-statics@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0" + version "2.5.0" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz#d2ca2dfc19c5a91c5a6615ce8e564ef0347e2a40" home-or-tmp@^2.0.0: version "2.0.0" @@ -4472,7 +4480,7 @@ is-descriptor@^0.1.0: is-data-descriptor "^0.1.4" kind-of "^5.0.0" -is-descriptor@^1.0.0: +is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" dependencies: @@ -4547,12 +4555,17 @@ is-installed-globally@0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" +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" + is-my-json-valid@^2.10.0: - version "2.17.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" + version "2.17.2" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" dependencies: generate-function "^2.0.0" generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" jsonpointer "^4.0.0" xtend "^4.0.0" @@ -4568,11 +4581,15 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-odd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-1.0.0.tgz#3b8a932eb028b3775c39bb09e91767accdb69088" +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + +is-odd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" dependencies: - is-number "^3.0.0" + is-number "^4.0.0" is-path-cwd@^1.0.0: version "1.0.0" @@ -4674,9 +4691,9 @@ is-whitespace-character@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz#9ae0176f3282b65457a1992cdb084f8a5f833e3b" -is-windows@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" is-word-character@^1.0.0: version "1.0.1" @@ -4720,24 +4737,24 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" istanbul-api@^1.1.14: - version "1.2.1" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.2.1.tgz#0c60a0515eb11c7d65c6b50bba2c6e999acd8620" + version "1.2.2" + resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.2.2.tgz#e17cd519dd5ec4141197f246fdf380b75487f3b1" dependencies: async "^2.1.4" fileset "^2.0.2" - istanbul-lib-coverage "^1.1.1" + istanbul-lib-coverage "^1.1.2" istanbul-lib-hook "^1.1.0" - istanbul-lib-instrument "^1.9.1" - istanbul-lib-report "^1.1.2" - istanbul-lib-source-maps "^1.2.2" - istanbul-reports "^1.1.3" + istanbul-lib-instrument "^1.9.2" + istanbul-lib-report "^1.1.3" + istanbul-lib-source-maps "^1.2.3" + istanbul-reports "^1.1.4" js-yaml "^3.7.0" mkdirp "^0.5.1" once "^1.4.0" -istanbul-lib-coverage@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" +istanbul-lib-coverage@^1.1.1, istanbul-lib-coverage@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz#4113c8ff6b7a40a1ef7350b01016331f63afde14" istanbul-lib-hook@^1.1.0: version "1.1.0" @@ -4745,40 +4762,40 @@ istanbul-lib-hook@^1.1.0: dependencies: append-transform "^0.4.0" -istanbul-lib-instrument@^1.7.5, istanbul-lib-instrument@^1.8.0, istanbul-lib-instrument@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz#250b30b3531e5d3251299fdd64b0b2c9db6b558e" +istanbul-lib-instrument@^1.7.5, istanbul-lib-instrument@^1.8.0, istanbul-lib-instrument@^1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.2.tgz#84905bf47f7e0b401d6b840da7bad67086b4aab6" dependencies: babel-generator "^6.18.0" babel-template "^6.16.0" babel-traverse "^6.18.0" babel-types "^6.18.0" babylon "^6.18.0" - istanbul-lib-coverage "^1.1.1" + istanbul-lib-coverage "^1.1.2" semver "^5.3.0" -istanbul-lib-report@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.2.tgz#922be27c13b9511b979bd1587359f69798c1d425" +istanbul-lib-report@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz#2df12188c0fa77990c0d2176d2d0ba3394188259" dependencies: - istanbul-lib-coverage "^1.1.1" + istanbul-lib-coverage "^1.1.2" mkdirp "^0.5.1" path-parse "^1.0.5" supports-color "^3.1.2" -istanbul-lib-source-maps@^1.2.1, istanbul-lib-source-maps@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.2.tgz#750578602435f28a0c04ee6d7d9e0f2960e62c1c" +istanbul-lib-source-maps@^1.2.1, istanbul-lib-source-maps@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz#20fb54b14e14b3fb6edb6aca3571fd2143db44e6" dependencies: debug "^3.1.0" - istanbul-lib-coverage "^1.1.1" + istanbul-lib-coverage "^1.1.2" mkdirp "^0.5.1" rimraf "^2.6.1" source-map "^0.5.3" -istanbul-reports@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.3.tgz#3b9e1e8defb6d18b1d425da8e8b32c5a163f2d10" +istanbul-reports@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.4.tgz#5ccba5e22b7b5a5d91d5e0a830f89be334bf97bd" dependencies: handlebars "^4.0.3" @@ -5172,7 +5189,7 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" -kind-of@^5.0.0, kind-of@^5.0.2: +kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" @@ -5605,19 +5622,15 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -"mime-db@>= 1.30.0 < 2": - version "1.32.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414" - -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" +"mime-db@>= 1.33.0 < 2", mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" -mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" +mime-types@^2.1.12, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" dependencies: - mime-db "~1.30.0" + mime-db "~1.33.0" mime@1.4.1: version "1.4.1" @@ -5695,6 +5708,10 @@ module-deps-sortable@4.0.6: through2 "^2.0.0" xtend "^4.0.0" +mousetrap@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.1.tgz#2a085f5c751294c75e7e81f6ec2545b29cbf42d9" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -5719,16 +5736,17 @@ nan@^2.3.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" nanomatch@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.7.tgz#53cd4aa109ff68b7f869591fdc9d10daeeea3e79" + version "1.2.8" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.8.tgz#e2fb86f002b408424731ad1c92564343c5063378" dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" fragment-cache "^0.2.1" - is-odd "^1.0.0" - kind-of "^5.0.2" + is-odd "^2.0.0" + is-windows "^1.0.2" + kind-of "^6.0.2" object.pick "^1.3.0" regex-not "^1.0.0" snapdragon "^0.8.1" @@ -6048,8 +6066,8 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" osenv@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -6572,12 +6590,12 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0 supports-color "^3.2.3" postcss@^6.0.1: - version "6.0.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.17.tgz#e259a051ca513f81e9afd0c21f7f82eda50c65c5" + version "6.0.19" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555" dependencies: - chalk "^2.3.0" + chalk "^2.3.1" source-map "^0.6.1" - supports-color "^5.1.0" + supports-color "^5.2.0" prelude-ls@~1.1.2: version "1.1.2" @@ -6747,8 +6765,8 @@ randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: safe-buffer "^5.1.0" randomfill@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62" + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -6799,6 +6817,22 @@ react-dom@^0.14.0: version "0.14.9" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-0.14.9.tgz#05064a3dcf0fb1880a3b2bfc9d58c55d8d9f6293" +react-editable-json-tree@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-editable-json-tree/-/react-editable-json-tree-2.1.0.tgz#c865ed0e77788f4512eea486f692f27563e645b7" + dependencies: + prop-types "^15.6.0" + react-hotkeys "^0.10.0" + +react-hotkeys@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/react-hotkeys/-/react-hotkeys-0.10.0.tgz#d1e78bd63f16d6db58d550d33c8eb071f35d94fb" + dependencies: + create-react-class "^15.5.2" + lodash "^4.13.1" + mousetrap "^1.5.2" + prop-types "^15.5.8" + react-jsonschema-form@0.50.1: version "0.50.1" resolved "https://registry.yarnpkg.com/react-jsonschema-form/-/react-jsonschema-form-0.50.1.tgz#30652f701645f3af25435ec5f6c42260c426b881" @@ -7888,7 +7922,7 @@ supports-color@^4.0.0, supports-color@^4.1.0, supports-color@^4.2.1: dependencies: has-flag "^2.0.0" -supports-color@^5.1.0, supports-color@^5.2.0: +supports-color@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a" dependencies: @@ -7951,8 +7985,8 @@ tar@^2.2.1: inherits "2" test-exclude@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" + version "4.2.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.0.tgz#07e3613609a362c74516a717515e13322ab45b3c" dependencies: arrify "^1.0.1" micromatch "^2.3.11" @@ -8124,11 +8158,11 @@ type-check@~0.3.2: prelude-ls "~1.1.2" type-is@~1.6.15: - version "1.6.15" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" + version "1.6.16" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" dependencies: media-typer "0.3.0" - mime-types "~2.1.15" + mime-types "~2.1.18" typedarray@^0.0.6, typedarray@~0.0.5: version "0.0.6" @@ -8139,8 +8173,8 @@ ua-parser-js@^0.7.9: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" uglify-js@3.3.x: - version "3.3.10" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.10.tgz#8e47821d4cf28e14c1826a0078ba0825ed094da8" + version "3.3.11" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.11.tgz#e9d058b20715138bb4e8e5cae2ea581686bdaae3" dependencies: commander "~2.14.1" source-map "~0.6.1"