diff --git a/frontend/package.json b/frontend/package.json index 37e3553da3..fbcfe0607b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -35,7 +35,6 @@ "lint:fix": "eslint . --ext js,jsx --fix", "test": "jest", "test:ci": "npm run lint && npm run build && npm run test", - "test:debug": "./node_modules/.bin/node-debug ./node_modules/.bin/jest -i --watch", "prepublish": "npm run build" }, "main": "./index.js", diff --git a/frontend/src/__mocks__/react-mdl.js b/frontend/src/__mocks__/react-mdl.js index b8fe741af9..dde54f173c 100644 --- a/frontend/src/__mocks__/react-mdl.js +++ b/frontend/src/__mocks__/react-mdl.js @@ -13,6 +13,8 @@ module.exports = { ListItem: 'react-mdl-ListItem', ListItemContent: 'react-mdl-ListItemContent', ListItemAction: 'react-mdl-ListItemAction', + Menu: 'react-mdl-Menu', + MenuItem: 'react-mdl-MenuItem', ProgressBar: 'react-mdl-ProgressBar', Switch: 'react-mdl-Switch', Tab: 'react-mdl-Tab', diff --git a/frontend/src/component/feature/form/__tests__/__snapshots__/form-add-feature-component-test.jsx.snap b/frontend/src/component/feature/form/__tests__/__snapshots__/form-add-feature-component-test.jsx.snap new file mode 100644 index 0000000000..32d202f00e --- /dev/null +++ b/frontend/src/component/feature/form/__tests__/__snapshots__/form-add-feature-component-test.jsx.snap @@ -0,0 +1,555 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`render the create feature page 1`] = ` +ShallowWrapper { + "length": 1, + Symbol(enzyme.__root__): [Circular], + Symbol(enzyme.__unrendered__): , + Symbol(enzyme.__renderer__): Object { + "batchedUpdates": [Function], + "getNode": [Function], + "render": [Function], + "simulateEvent": [Function], + "unmount": [Function], + }, + Symbol(enzyme.__node__): Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children":
+ + +
+
+ + Enabled + +
+
+ +
+ +
, + "onSubmit": undefined, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + , + , +
+
+ + Enabled + +
+
, + , +
, + , + ], + "style": Object { + "padding": "16px", + }, + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "error": Object {}, + "floatingLabel": true, + "label": "Name", + "name": "name", + "onBlur": [Function], + "onChange": [Function], + "required": true, + "value": "feature", + }, + "ref": null, + "rendered": null, + "type": "react-mdl-Textfield", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "floatingLabel": true, + "label": "Description", + "onChange": [Function], + "required": true, + "rows": 1, + "style": Object { + "width": "100%", + }, + "value": "Description", + }, + "ref": null, + "rendered": null, + "type": "react-mdl-Textfield", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ +
, + + Enabled + , +
, + ], + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object {}, + "ref": null, + "rendered": null, + "type": "br", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "checked": false, + "children": "Enabled", + "onChange": [Function], + }, + "ref": null, + "rendered": "Enabled", + "type": "react-mdl-Switch", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object {}, + "ref": null, + "rendered": null, + "type": "hr", + }, + ], + "type": "div", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "addStrategy": [MockFunction], + "configuredStrategies": Array [], + "moveStrategy": [MockFunction], + "removeStrategy": [MockFunction], + "updateStrategy": [MockFunction], + }, + "ref": null, + "rendered": null, + "type": "StrategiesSection", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object {}, + "ref": null, + "rendered": null, + "type": "br", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "function", + "props": Object { + "onCancel": [MockFunction], + "submitText": "Create", + }, + "ref": null, + "rendered": null, + "type": [Function], + }, + ], + "type": "section", + }, + "type": "form", + }, + Symbol(enzyme.__nodes__): Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children":
+ + +
+
+ + Enabled + +
+
+ +
+ +
, + "onSubmit": undefined, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + , + , +
+
+ + Enabled + +
+
, + , +
, + , + ], + "style": Object { + "padding": "16px", + }, + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "error": Object {}, + "floatingLabel": true, + "label": "Name", + "name": "name", + "onBlur": [Function], + "onChange": [Function], + "required": true, + "value": "feature", + }, + "ref": null, + "rendered": null, + "type": "react-mdl-Textfield", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "floatingLabel": true, + "label": "Description", + "onChange": [Function], + "required": true, + "rows": 1, + "style": Object { + "width": "100%", + }, + "value": "Description", + }, + "ref": null, + "rendered": null, + "type": "react-mdl-Textfield", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ +
, + + Enabled + , +
, + ], + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object {}, + "ref": null, + "rendered": null, + "type": "br", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "checked": false, + "children": "Enabled", + "onChange": [Function], + }, + "ref": null, + "rendered": "Enabled", + "type": "react-mdl-Switch", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object {}, + "ref": null, + "rendered": null, + "type": "hr", + }, + ], + "type": "div", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "addStrategy": [MockFunction], + "configuredStrategies": Array [], + "moveStrategy": [MockFunction], + "removeStrategy": [MockFunction], + "updateStrategy": [MockFunction], + }, + "ref": null, + "rendered": null, + "type": "StrategiesSection", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object {}, + "ref": null, + "rendered": null, + "type": "br", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "function", + "props": Object { + "onCancel": [MockFunction], + "submitText": "Create", + }, + "ref": null, + "rendered": null, + "type": [Function], + }, + ], + "type": "section", + }, + "type": "form", + }, + ], + Symbol(enzyme.__options__): Object { + "adapter": ReactSixteenAdapter { + "options": Object { + "enableComponentDidUpdateOnSetState": true, + }, + }, + }, +} +`; diff --git a/frontend/src/component/feature/form/__tests__/__snapshots__/form-update-feature-component-test.jsx.snap b/frontend/src/component/feature/form/__tests__/__snapshots__/form-update-feature-component-test.jsx.snap new file mode 100644 index 0000000000..8125a56293 --- /dev/null +++ b/frontend/src/component/feature/form/__tests__/__snapshots__/form-update-feature-component-test.jsx.snap @@ -0,0 +1,245 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`render the create feature page 1`] = ` +ShallowWrapper { + "length": 1, + Symbol(enzyme.__root__): [Circular], + Symbol(enzyme.__unrendered__): , + Symbol(enzyme.__renderer__): Object { + "batchedUpdates": [Function], + "getNode": [Function], + "render": [Function], + "simulateEvent": [Function], + "unmount": [Function], + }, + Symbol(enzyme.__node__): Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children":
+ +
+ +
, + "onSubmit": undefined, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + , +
, + , + ], + "style": Object { + "padding": "16px", + }, + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "addStrategy": [MockFunction], + "configuredStrategies": Array [], + "moveStrategy": [MockFunction], + "removeStrategy": [MockFunction], + "updateStrategy": [MockFunction], + }, + "ref": null, + "rendered": null, + "type": "StrategiesSection", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object {}, + "ref": null, + "rendered": null, + "type": "br", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "function", + "props": Object { + "onCancel": [MockFunction], + "submitText": "Update", + }, + "ref": null, + "rendered": null, + "type": [Function], + }, + ], + "type": "section", + }, + "type": "form", + }, + Symbol(enzyme.__nodes__): Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children":
+ +
+ +
, + "onSubmit": undefined, + }, + "ref": null, + "rendered": Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + , +
, + , + ], + "style": Object { + "padding": "16px", + }, + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "addStrategy": [MockFunction], + "configuredStrategies": Array [], + "moveStrategy": [MockFunction], + "removeStrategy": [MockFunction], + "updateStrategy": [MockFunction], + }, + "ref": null, + "rendered": null, + "type": "StrategiesSection", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object {}, + "ref": null, + "rendered": null, + "type": "br", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "function", + "props": Object { + "onCancel": [MockFunction], + "submitText": "Update", + }, + "ref": null, + "rendered": null, + "type": [Function], + }, + ], + "type": "section", + }, + "type": "form", + }, + ], + Symbol(enzyme.__options__): Object { + "adapter": ReactSixteenAdapter { + "options": Object { + "enableComponentDidUpdateOnSetState": true, + }, + }, + }, +} +`; diff --git a/frontend/src/component/feature/form/__tests__/__snapshots__/strategy-add-test.jsx.snap b/frontend/src/component/feature/form/__tests__/__snapshots__/strategy-add-test.jsx.snap new file mode 100644 index 0000000000..b0d06f4124 --- /dev/null +++ b/frontend/src/component/feature/form/__tests__/__snapshots__/strategy-add-test.jsx.snap @@ -0,0 +1,296 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders add strategy form with a list of available strategies 1`] = ` +ShallowWrapper { + "length": 1, + Symbol(enzyme.__root__): [Circular], + Symbol(enzyme.__unrendered__): , + Symbol(enzyme.__renderer__): Object { + "batchedUpdates": [Function], + "getNode": [Function], + "render": [Function], + "simulateEvent": [Function], + "unmount": [Function], + }, + Symbol(enzyme.__node__): Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + , + + + Add Strategy: + + + default + + , + ], + "style": Object { + "display": "inline-block", + "height": "25px", + "position": "relative", + "width": "25px", + }, + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "accent": true, + "id": "strategies-add", + "name": "add", + "onClick": [Function], + "raised": true, + "title": "Add Strategy", + }, + "ref": null, + "rendered": null, + "type": "react-mdl-IconButton", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "align": "right", + "children": Array [ + + Add Strategy: + , + Array [ + + default + , + ], + ], + "ripple": true, + "style": Object { + "backgroundColor": "rgb(247, 248, 255)", + "maxHeight": "300px", + "overflowY": "auto", + }, + "target": "strategies-add", + "valign": "bottom", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "Add Strategy:", + "disabled": true, + }, + "ref": null, + "rendered": "Add Strategy:", + "type": "react-mdl-MenuItem", + }, + Object { + "instance": null, + "key": "default", + "nodeType": "host", + "props": Object { + "children": "default", + "onClick": [Function], + "title": "Default on/off strategy.", + }, + "ref": null, + "rendered": "default", + "type": "react-mdl-MenuItem", + }, + ], + "type": "react-mdl-Menu", + }, + ], + "type": "div", + }, + Symbol(enzyme.__nodes__): Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": Array [ + , + + + Add Strategy: + + + default + + , + ], + "style": Object { + "display": "inline-block", + "height": "25px", + "position": "relative", + "width": "25px", + }, + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "accent": true, + "id": "strategies-add", + "name": "add", + "onClick": [Function], + "raised": true, + "title": "Add Strategy", + }, + "ref": null, + "rendered": null, + "type": "react-mdl-IconButton", + }, + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "align": "right", + "children": Array [ + + Add Strategy: + , + Array [ + + default + , + ], + ], + "ripple": true, + "style": Object { + "backgroundColor": "rgb(247, 248, 255)", + "maxHeight": "300px", + "overflowY": "auto", + }, + "target": "strategies-add", + "valign": "bottom", + }, + "ref": null, + "rendered": Array [ + Object { + "instance": null, + "key": undefined, + "nodeType": "host", + "props": Object { + "children": "Add Strategy:", + "disabled": true, + }, + "ref": null, + "rendered": "Add Strategy:", + "type": "react-mdl-MenuItem", + }, + Object { + "instance": null, + "key": "default", + "nodeType": "host", + "props": Object { + "children": "default", + "onClick": [Function], + "title": "Default on/off strategy.", + }, + "ref": null, + "rendered": "default", + "type": "react-mdl-MenuItem", + }, + ], + "type": "react-mdl-Menu", + }, + ], + "type": "div", + }, + ], + Symbol(enzyme.__options__): Object { + "adapter": ReactSixteenAdapter { + "options": Object { + "enableComponentDidUpdateOnSetState": true, + }, + }, + }, +} +`; diff --git a/frontend/src/component/feature/form/__tests__/form-add-feature-component-test.jsx b/frontend/src/component/feature/form/__tests__/form-add-feature-component-test.jsx new file mode 100644 index 0000000000..52b4f03dc5 --- /dev/null +++ b/frontend/src/component/feature/form/__tests__/form-add-feature-component-test.jsx @@ -0,0 +1,124 @@ +import React from 'react'; +import AddFeatureComponent from './../form-add-feature-component'; +import { shallow } from 'enzyme/build/index'; + +jest.mock('react-mdl'); +jest.mock('../strategies-section-container', () => 'StrategiesSection'); + +it('render the create feature page', () => { + let input = { + name: 'feature', + nameError: {}, + description: 'Description', + enabled: false, + }; + const tree = shallow( + + ); + expect(tree).toMatchSnapshot(); +}); + +let input = { + name: 'feature', + nameError: {}, + description: 'Description', + enabled: false, +}; + +let validateName = jest.fn(); +let setValue = jest.fn(); +let onSubmit = jest.fn(); +let addStrategy = jest.fn(); +let removeStrategy = jest.fn(); +let moveStrategy = jest.fn(); +let onCancel = jest.fn(); +let updateStratgy = jest.fn(); +let init = jest.fn(); +let eventMock = { + preventDefault: () => {}, + stopPropagation: () => {}, + target: { + name: 'NAME', + }, +}; +const buildComponent = (setValue, validateName) => ( + +); + +it('add a feature name with validation', () => { + let called = false; + validateName = () => { + called = true; + }; + const wrapper = shallow(buildComponent(setValue, validateName)); + wrapper + .find('react-mdl-Textfield') + .first() + .simulate('blur', eventMock); + expect(called).toBe(true); +}); + +it('set a value for feature name', () => { + let called = false; + setValue = () => { + called = true; + }; + let wrapper = shallow(buildComponent(setValue, validateName)); + wrapper + .find('react-mdl-Textfield') + .first() + .simulate('change', eventMock); + expect(called).toBe(true); +}); + +it('set a description for feature name', () => { + let called = false; + setValue = () => { + called = true; + }; + let wrapper = shallow(buildComponent(setValue, validateName)); + wrapper + .find('react-mdl-Textfield') + .last() + .simulate('change', eventMock); + expect(called).toBe(true); +}); + +it('switch the toggle', () => { + let called = false; + setValue = () => { + called = true; + }; + let wrapper = shallow(buildComponent(setValue, validateName)); + eventMock.target.enabled = false; + wrapper + .find('react-mdl-Switch') + .last() + .simulate('change', eventMock); + expect(called).toBe(true); +}); diff --git a/frontend/src/component/feature/form/__tests__/form-update-feature-component-test.jsx b/frontend/src/component/feature/form/__tests__/form-update-feature-component-test.jsx new file mode 100644 index 0000000000..845fed1c53 --- /dev/null +++ b/frontend/src/component/feature/form/__tests__/form-update-feature-component-test.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import UpdateFeatureComponent from './../form-update-feature-component'; +import { shallow } from 'enzyme/build/index'; + +jest.mock('react-mdl'); +jest.mock('../strategies-section-container', () => 'StrategiesSection'); + +it('render the create feature page', () => { + let input = { + name: 'feature', + nameError: {}, + description: 'Description', + enabled: false, + }; + const tree = shallow( + + ); + expect(tree).toMatchSnapshot(); +}); diff --git a/frontend/src/component/feature/form/__tests__/strategy-add-test.jsx b/frontend/src/component/feature/form/__tests__/strategy-add-test.jsx new file mode 100644 index 0000000000..46a35c6130 --- /dev/null +++ b/frontend/src/component/feature/form/__tests__/strategy-add-test.jsx @@ -0,0 +1,46 @@ +import React from 'react'; +import AddStrategy from './../strategies-add'; +import { shallow } from 'enzyme/build/index'; + +jest.mock('react-mdl'); + +const strategies = [ + { + name: 'default', + editable: false, + description: 'Default on/off strategy.', + parameters: ['t'], + }, +]; +let addStrategy = jest.fn(); +let fetchStrategies = jest.fn(); +let eventMock = { + preventDefault: () => {}, + stopPropagation: () => {}, + target: { + name: 'default', + }, +}; +const buildComponent = (addStrategy, fetchStrategies, strategies) => ( + +); + +it('renders add strategy form with a list of available strategies', () => { + const tree = shallow(buildComponent(addStrategy, fetchStrategies, strategies)); + expect(tree).toMatchSnapshot(); +}); + +it('add a strategy', () => { + let called = false; + addStrategy = () => { + called = true; + }; + const addStrategyProto = jest.spyOn(AddStrategy.prototype, 'addStrategy'); + const wrapper = shallow(buildComponent(addStrategy, fetchStrategies, strategies)); + wrapper + .find('react-mdl-MenuItem') + .last() + .simulate('click', eventMock); + expect(called).toBe(true); + expect(addStrategyProto).toHaveBeenCalled(); +}); diff --git a/frontend/src/component/feature/form/__tests__/strategy-input-list-test.jsx b/frontend/src/component/feature/form/__tests__/strategy-input-list-test.jsx index 31e1032daa..ad49344c7c 100644 --- a/frontend/src/component/feature/form/__tests__/strategy-input-list-test.jsx +++ b/frontend/src/component/feature/form/__tests__/strategy-input-list-test.jsx @@ -66,3 +66,16 @@ it('spy onBlur', () => { wrapper.find('react-mdl-Textfield').simulate('blur', focusMock); expect(onFocus).toHaveBeenCalled(); }); + +it('spy onClose', () => { + let list = ['item1']; + const name = 'featureName'; + const onClose = jest.spyOn(InputList.prototype, 'onClose'); + let closeMock = { + preventDefault: () => {}, + stopPropagation: () => {}, + }; + const wrapper = shallow(); + wrapper.find('react-mdl-Chip').simulate('close', closeMock); + expect(onClose).toHaveBeenCalled(); +}); diff --git a/frontend/src/component/feature/form/strategies-add.jsx b/frontend/src/component/feature/form/strategies-add.jsx index a75de9fdc9..aac8731fb5 100644 --- a/frontend/src/component/feature/form/strategies-add.jsx +++ b/frontend/src/component/feature/form/strategies-add.jsx @@ -9,7 +9,7 @@ class AddStrategy extends React.Component { fetchStrategies: PropTypes.func.isRequired, }; - addStrategy = strategyName => { + addStrategy(strategyName) { const selectedStrategy = this.props.strategies.find(s => s.name === strategyName); const parameters = {}; @@ -21,7 +21,7 @@ class AddStrategy extends React.Component { name: selectedStrategy.name, parameters, }); - }; + } stopPropagation(e) { e.stopPropagation();