Repository: mlaursen/react-md
Pull request #79 (2016-05-10 19:44:35)

Added Initial Ink Tests
This should complete #45 and the Ink part for #20 


Patch:
diff --git a/src/js/Inks/injectInk.js b/src/js/Inks/injectInk.js
index bd233aa4c1..506200a3aa 100644
--- a/src/js/Inks/injectInk.js
+++ b/src/js/Inks/injectInk.js
@@ -10,10 +10,12 @@ import { getOffset } from '../utils';
 /**
  * Takes any component and injects an ink container along with event
  * listeners for handling those inks. It also injects a prop
- * named `ink` which needs to be added to the ComposedComponent.
+ * named `ink` which needs to be added to the `ComposedComponent`.
  *
+ * ```js
  * @param ComposedComponent the component to compose with the ink functionality.
  * @return the ComposedComponent with inks.
+ * ```
  */
 export default ComposedComponent => class Ink extends Component {
   constructor(props) {
@@ -26,17 +28,55 @@ export default ComposedComponent => class Ink extends Component {
   }
 
   static propTypes = {
+    /**
+     * An optional onMouseUp function to call along with the ink creation onMouseUp.
+     */
     onMouseUp: PropTypes.func,
+
+    /**
+     * An optional onMouseDown function to call along with the ink creation onMouseDown.
+     */
     onMouseDown: PropTypes.func,
+
+    /**
+     * An optional onMouseLeave function to call along with the ink creation onMouseLeave.
+     */
     onMouseLeave: PropTypes.func,
+
+    /**
+     * An optional onFocus function to call along with the ink creation onFocus.
+     */
     onFocus: PropTypes.func,
+
+    /**
+     * An optional onBlur function to call along with the ink creation onBlur.
+     */
     onBlur: PropTypes.func,
+
+    /**
+     * An optional onTouchStart function to call along with the ink creation onTouchStart.
+     */
     onTouchStart: PropTypes.func,
+
+    /**
+     * An optional onTouchEnd function to call along with the ink creation onTouchEnd.
+     */
     onTouchEnd: PropTypes.func,
+
+    /**
+     * An optional onTouchCancel function to call along with the ink creation onTouchCancel.
+     */
     onTouchCancel: PropTypes.func,
+
+    /**
+     * Boolean if the ink or the composed component is disabled.
+     */
     disabled: PropTypes.bool,
+
+    /**
+     * Boolean if only the ink is disabled.
+     */
     inkDisabled: PropTypes.bool,
-    children: PropTypes.node,
   };
 
   calcR = (a, b) => {
@@ -162,12 +202,12 @@ export default ComposedComponent => class Ink extends Component {
   };
 
   render() {
-    const { children, ...props } = this.props;
+    const { ...props } = this.props;
     delete props.inkDisabled;
 
     // Don't inject ink and new props if disabled
     if(this.disabled()) {
-      return <ComposedComponent {...props} children={children} />;
+      return <ComposedComponent {...props} />;
     }
 
     const ink = (
@@ -188,9 +228,7 @@ export default ComposedComponent => class Ink extends Component {
         onTouchCancel={this.handleTouchCancel}
         onTouchEnd={this.handleTouchEnd}
         ink={ink}
-      >
-        {children}
-      </ComposedComponent>
+      />
     );
   }
 };
diff --git a/src/js/utils/__mocks__/index.js b/src/js/utils/__mocks__/index.js
new file mode 100644
index 0000000000..31e254bb0d
--- /dev/null
+++ b/src/js/utils/__mocks__/index.js
@@ -0,0 +1,9 @@
+/*eslint-env jest*/
+export const getOffset = jest.genMockFunction().mockImplementation(() => {
+  return {
+    left: 0,
+    top: 0,
+  };
+});
+
+export const animate = jest.genMockFunction();


Test patch:
diff --git a/src/js/Inks/__tests__/Ink.js b/src/js/Inks/__tests__/Ink.js
new file mode 100644
index 0000000000..dbcfac31a7
--- /dev/null
+++ b/src/js/Inks/__tests__/Ink.js
@@ -0,0 +1,167 @@
+/*eslint-env jest*/
+/*eslint-disable react/prop-types*/
+jest.unmock('../injectInk');
+jest.unmock('../../constants/keyCodes');
+
+import React from 'react';
+import {
+  Simulate,
+  renderIntoDocument,
+  findRenderedComponentWithType,
+  scryRenderedComponentsWithType,
+  findRenderedDOMComponentWithTag,
+  scryRenderedDOMComponentsWithClass,
+} from 'react-addons-test-utils';
+
+import injectInk from '../injectInk';
+import InkTransition from '../InkTransition';
+import { LEFT_MOUSE, RIGHT_MOUSE } from '../../constants/keyCodes';
+
+class Test extends React.Component {
+  render() {
+    const { ink, children, ...props } = this.props;
+    return <button {...props}>{ink}{children}</button>;
+  }
+}
+const InkTest = injectInk(Test);
+
+
+describe('injectInk', () => {
+  it('injects an ink prop into a React component', () => {
+    const inkTest = renderIntoDocument(
+      <InkTest>Hello!</InkTest>
+    );
+
+    const testComp = findRenderedComponentWithType(inkTest, Test);
+    expect(testComp.props.ink).toBeDefined();
+  });
+
+  it('does not inject an ink if the component is disabled or the ink is disabled by a prop', () => {
+    const disabled = renderIntoDocument(
+      <InkTest disabled>Hello!</InkTest>
+    );
+
+    const disabledComp = findRenderedComponentWithType(disabled, Test);
+    expect(disabledComp.props.ink).not.toBeDefined();
+
+    const inkDisabled = renderIntoDocument(
+      <InkTest inkDisabled={true}>Hello!</InkTest>
+    );
+
+    const inkDisabledComp = findRenderedComponentWithType(inkDisabled, Test);
+    expect(inkDisabledComp.props.ink).not.toBeDefined();
+  });
+
+  it('allows for the touch, click, and focus event listeners to be passed down', () => {
+    const onMouseUp = jest.genMockFunction();
+    const onMouseDown = jest.genMockFunction();
+    const onMouseLeave = jest.genMockFunction();
+    const onFocus = jest.genMockFunction();
+    const onBlur = jest.genMockFunction();
+    const onTouchStart = jest.genMockFunction();
+    const onTouchCancel = jest.genMockFunction();
+    const onTouchEnd = jest.genMockFunction();
+
+    const inkTest = renderIntoDocument(
+      <InkTest
+        onMouseUp={onMouseUp}
+        onMouseDown={onMouseDown}
+        onMouseLeave={onMouseLeave}
+        onFocus={onFocus}
+        onBlur={onBlur}
+        onTouchStart={onTouchStart}
+        onTouchCancel={onTouchCancel}
+        onTouchEnd={onTouchEnd}
+      >
+        Hello!
+      </InkTest>
+    );
+
+    const testNode = findRenderedDOMComponentWithTag(inkTest, 'button');
+    const event = { pageX: 0, pageY: 0 };
+    const touchEvent = { changedTouches: [event] };
+    Simulate.mouseDown(testNode, event);
+    Simulate.mouseUp(testNode, event);
+    Simulate.mouseLeave(testNode, event);
+    Simulate.focus(testNode);
+    Simulate.blur(testNode);
+    Simulate.touchStart(testNode, touchEvent);
+    Simulate.touchCancel(testNode, touchEvent);
+    Simulate.touchEnd(testNode, touchEvent);
+
+    expect(onMouseDown.mock.calls.length).toBe(1);
+    expect(onMouseUp.mock.calls.length).toBe(1);
+    expect(onMouseLeave.mock.calls.length).toBe(1);
+    expect(onFocus.mock.calls.length).toBe(1);
+    expect(onBlur.mock.calls.length).toBe(1);
+    expect(onTouchStart.mock.calls.length).toBe(1);
+    expect(onTouchCancel.mock.calls.length).toBe(1);
+    expect(onTouchEnd.mock.calls.length).toBe(1);
+  });
+
+  it('does not create an ink when the right mouse button is clicked or control clicked', () => {
+    const inkTest = renderIntoDocument(
+      <InkTest>Hello</InkTest>
+    );
+
+    const button = findRenderedDOMComponentWithTag(inkTest, 'button');
+    let inks = scryRenderedDOMComponentsWithClass(inkTest, 'md-ink');
+    expect(inks.length).toBe(0);
+
+    Simulate.mouseDown(button, { button: RIGHT_MOUSE });
+    Simulate.mouseDown(button, { button: LEFT_MOUSE, ctrlKey: true });
+
+    inks = scryRenderedComponentsWithType(inkTest, InkTransition);
+    expect(inks.length).toBe(0);
+  });
+
+  it('creates an ink on left mouse down', () => {
+    const inkTest = renderIntoDocument(
+      <InkTest>Hello</InkTest>
+    );
+
+    const button = findRenderedDOMComponentWithTag(inkTest, 'button');
+    let inks = scryRenderedComponentsWithType(inkTest, InkTransition);
+    expect(inks.length).toBe(0);
+
+    Simulate.mouseDown(button, { button: LEFT_MOUSE });
+
+    inks = scryRenderedComponentsWithType(inkTest, InkTransition);
+    expect(inks.length).toBe(1);
+  });
+
+  it('creates an ink on touch start', () => {
+    const inkTest = renderIntoDocument(
+      <InkTest>Hello</InkTest>
+    );
+
+    const button = findRenderedDOMComponentWithTag(inkTest, 'button');
+    let inks = scryRenderedComponentsWithType(inkTest, InkTransition);
+    expect(inks.length).toBe(0);
+
+    Simulate.touchStart(button, { changedTouches: [{}] });
+
+    inks = scryRenderedComponentsWithType(inkTest, InkTransition);
+    expect(inks.length).toBe(1);
+  });
+
+  it('creates an ink on focus and removes on blur', () => {
+    const inkTest = renderIntoDocument(
+      <InkTest>Hello</InkTest>
+    );
+
+    const button = findRenderedDOMComponentWithTag(inkTest, 'button');
+    let inks = scryRenderedComponentsWithType(inkTest, InkTransition);
+    expect(inks.length).toBe(0);
+
+    Simulate.focus(button);
+
+    inks = scryRenderedComponentsWithType(inkTest, InkTransition);
+    expect(inks.length).toBe(1);
+
+    Simulate.blur(button);
+
+    inks = scryRenderedComponentsWithType(inkTest, InkTransition);
+    expect(inks.length).toBe(0);
+  });
+});