Repository: react-materialize/react-materialize (js)

Issue:
3.0.0 Toast.js
### Upgrade to latest materialize-css@1.0.0-rc.2

AC
- Branch off 3.0.0-beta.0
- Check that the component works
- Keep jQuery initialisation of component if exists
- Update with new available modifiers and options
- Update propTypes and description
- Update examples page
- Create PR into branch 3.0.0-beta.0


Pull request description:
New Toast implementation + specs
# Description

Adapts Toast component to new materialize-css implementation
Fixes #610

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [x] This change requires a documentation update

# How Has This Been Tested?

Unit specs and manually while developing

# Checklist:

- [x] I have commented my code, particularly in hard-to-understand areas
- [x] My changes generate no new warnings
- [ ] I have not generated a new package version. (the maintainers will handle that)


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a4b701a..79ec129 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Changelog
 
+### 3.0.0
+
+- (BREAKING) Toast [new implementation]
+- ... add changes here ...
+
 ### 2.3.3
 
 - Fixes lib not uploading
diff --git a/docs/src/pages/ToastPage.js b/docs/src/pages/ToastPage.js
index 7914f24..d41a1d2 100644
--- a/docs/src/pages/ToastPage.js
+++ b/docs/src/pages/ToastPage.js
@@ -9,19 +9,18 @@ import toastCode from '!raw-loader!Toast';
 const ToastPage = () => (
   <Row>
     <Col m={9} s={12} l={10}>
-      <p className='caption'>
-        Materialize provides an easy way for you to send unobtrusive alerts to your users through toasts.
-        These toasts are also placed and sized responsively,
-        try it out by clicking the button below on different device sizes.
+      <p className="caption">
+        Materialize provides an easy way for you to send unobtrusive alerts to
+        your users through toasts. These toasts are also placed and sized
+        responsively, try it out by clicking the button below on
+        different device sizes.
       </p>
       <Col s={12}>
-        <ReactPlayground code={Samples.toast}>
-          {toast}
-        </ReactPlayground>
+        <ReactPlayground code={Samples.toast} />
       </Col>
 
       <Col s={12}>
-        <PropTable header='Toast' component={toastCode} />
+        <PropTable header="Toast" component={toastCode} />
       </Col>
     </Col>
   </Row>
diff --git a/examples/Toast.js b/examples/Toast.js
index 85a8063..b1a96d0 100644
--- a/examples/Toast.js
+++ b/examples/Toast.js
@@ -2,6 +2,4 @@ import React from 'react';
 import Toast from '../src/Toast';
 
 export default
-<Toast toast="here you go!">
-Toast
-</Toast>;
+<Toast options={{ html: 'Here you go!' }}>Toast</Toast>;
diff --git a/src/Toast.js b/src/Toast.js
index ba80af6..f67ee18 100644
--- a/src/Toast.js
+++ b/src/Toast.js
@@ -4,33 +4,65 @@ import cx from 'classnames';
 
 import Button from './Button';
 
-class Toast extends Component {
-  constructor(props) {
-    super(props);
-    this.onClick = this.onClick.bind(this);
-  }
+const Toast = props => {
+  const { children, className, options = {} } = props;
 
-  render() {
-    const { children, rounded, className } = this.props;
-    const classes = { toast: true, rounded: rounded };
+  const showToast = () => M.toast(options);
 
-    return (
-      <Button onClick={this.onClick} className={cx(classes, className)}>
-        {children}
-      </Button>
-    );
-  }
-
-  onClick() {
-    Materialize.toast(this.props.toast, 1000);
-  }
-}
+  return (
+    <Button onClick={showToast} className={cx('toast', className)}>
+      {children}
+    </Button>
+  );
+};
 
 Toast.propTypes = {
   className: PropTypes.string,
-  toast: PropTypes.string.isRequired,
+  /*
+   * Toast trigger content
+   */
   children: PropTypes.node,
-  rounded: PropTypes.bool
+  /*
+   * Options to pass to Toast method
+   * <a href="https://materializecss.com/toasts.html">More</a>
+   */
+  options: PropTypes.shape({
+    /*
+     * The HTML content of the Toast.
+     * @default ''
+     */
+    html: PropTypes.string,
+    /*
+     * Length in ms the Toast stays before dismissal.
+     * @default 4000
+     */
+    displayLength: PropTypes.number,
+    /*
+     * Transition in duration in milliseconds.
+     * @default 300
+     */
+    inDuration: PropTypes.number,
+    /*
+     * Transition out duration in milliseconds.
+     * @default 375
+     */
+    outDuration: PropTypes.number,
+    /*
+     * Classes to be added to the toast element.
+     * @default ''
+     */
+    classes: PropTypes.string,
+    /*
+     * Callback function called when toast is dismissed.
+     * @default null
+     */
+    completeCallback: PropTypes.func,
+    /*
+     * The percentage of the toast's width it takes for a drag to dismiss a Toast.
+     * @default 0.8
+     */
+    activationPercent: PropTypes.number
+  })
 };
 
 export default Toast;


Test patch:
diff --git a/test/Toast.spec.js b/test/Toast.spec.js
new file mode 100644
index 0000000..cc3d6c3
--- /dev/null
+++ b/test/Toast.spec.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import Toast from '../src/Toast';
+import mocker from './helper/new-mocker';
+
+describe('Toast', () => {
+  const options = {
+    html: 'foo',
+    classes: 'bar'
+  };
+
+  const toastMock = jest.fn();
+  const restore = mocker('toast', toastMock);
+
+  afterAll(() => {
+    restore();
+  });
+
+  const child = 'toast content';
+
+  const wrapper = shallow(<Toast options={options}>{child}</Toast>);
+
+  test('renders', () => {
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  test('should create a child element', () => {
+    expect(wrapper.contains(child)).toEqual(true);
+  });
+
+  test('calls Toast with clicked with options', () => {
+    wrapper.simulate('click');
+    expect(toastMock).toHaveBeenCalledWith(options);
+  });
+});
diff --git a/test/__snapshots__/Toast.spec.js.snap b/test/__snapshots__/Toast.spec.js.snap
new file mode 100644
index 0000000..02b7711
--- /dev/null
+++ b/test/__snapshots__/Toast.spec.js.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Toast renders 1`] = `
+<Button
+  className="toast"
+  node="button"
+  onClick={[Function]}
+>
+  toast content
+</Button>
+`;
diff --git a/test/helper/new-mocker.js b/test/helper/new-mocker.js
new file mode 100644
index 0000000..f724ff8
--- /dev/null
+++ b/test/helper/new-mocker.js
@@ -0,0 +1,8 @@
+export default (name, mock) => {
+  const actual = M[name];
+  M[name] = mock;
+
+  return () => {
+    M[name] = actual;
+  };
+};
diff --git a/test/setup.js b/test/setup.js
index 15beef2..6fdaf34 100644
--- a/test/setup.js
+++ b/test/setup.js
@@ -3,5 +3,7 @@ import Enzyme from 'enzyme';
 import Adapter from 'enzyme-adapter-react-16';
 
 global.$ = require('jquery');
+window.Hammer = require('materialize-css/js/hammer.min.js');
+global.M = require('materialize-css');
 
 Enzyme.configure({ adapter: new Adapter() });