From ca2a12808655f8902336b8166f14c233f558f1ec Mon Sep 17 00:00:00 2001 From: Benjy Cui Date: Tue, 10 Oct 2017 10:39:26 +0800 Subject: [PATCH] feat: make Notification.newInstance to return a Promise, close: #21 --- README.md | 9 +- examples/simple.js | 3 +- src/Notification.jsx | 41 +++++---- tests/index.js | 215 ++++++++++++++++++++++++++----------------- 4 files changed, 161 insertions(+), 107 deletions(-) diff --git a/README.md b/README.md index 4bc197b..3adc631 100644 --- a/README.md +++ b/README.md @@ -51,15 +51,16 @@ online example: http://react-component.github.io/notification/examples/ ```js var Notification = require('rc-notification'); -var notification = Notification.newInstance(); -notification.notice({ - content: 'content' +Notification.newInstance({}, notification => { + notification.notice({ + content: 'content' + }); }); ``` ## API -### Notification.newInstance(props) +### Notification.newInstance(props, (notification) => void) => void props details: diff --git a/examples/simple.js b/examples/simple.js index 8bd76f3..8aee3be 100644 --- a/examples/simple.js +++ b/examples/simple.js @@ -3,7 +3,8 @@ import 'rc-notification/assets/index.less'; import Notification from 'rc-notification'; import React from 'react'; import ReactDOM from 'react-dom'; -const notification = Notification.newInstance({}); +let notification = null; +Notification.newInstance({}, (n) => notification = n); function simpleFn() { notification.notice({ diff --git a/src/Notification.jsx b/src/Notification.jsx index 0927c80..e3017ed 100644 --- a/src/Notification.jsx +++ b/src/Notification.jsx @@ -87,7 +87,7 @@ class Notification extends Component { } } -Notification.newInstance = function newNotificationInstance(properties) { +Notification.newInstance = function newNotificationInstance(properties, callback) { const { getContainer, ...props } = properties || {}; let div; if (getContainer) { @@ -96,22 +96,29 @@ Notification.newInstance = function newNotificationInstance(properties) { div = document.createElement('div'); document.body.appendChild(div); } - const notification = ReactDOM.render(, div); - return { - notice(noticeProps) { - notification.add(noticeProps); - }, - removeNotice(key) { - notification.remove(key); - }, - component: notification, - destroy() { - ReactDOM.unmountComponentAtNode(div); - if (!getContainer) { - document.body.removeChild(div); - } - }, - }; + let called = false; + function ref(notification) { + if (called) { + return; + } + called = true; + callback({ + notice(noticeProps) { + notification.add(noticeProps); + }, + removeNotice(key) { + notification.remove(key); + }, + component: notification, + destroy() { + ReactDOM.unmountComponentAtNode(div); + if (!getContainer) { + document.body.removeChild(div); + } + }, + }); + } + ReactDOM.render(, div); }; export default Notification; diff --git a/tests/index.js b/tests/index.js index a0994c8..c6db1a5 100644 --- a/tests/index.js +++ b/tests/index.js @@ -1,6 +1,7 @@ import 'core-js/es6/map'; import 'core-js/es6/set'; import React from 'react'; +import ReactDOM from 'react-dom'; import TestUtils from 'react-dom/test-utils'; import expect from 'expect.js'; @@ -10,117 +11,161 @@ require('../assets/index.less'); describe('rc-notification', () => { it('works', (done) => { - const notification = Notification.newInstance(); - notification.notice({ - content:

1

, - duration: 0.1, + Notification.newInstance({}, notification => { + notification.notice({ + content:

1

, + duration: 0.1, + }); + setTimeout(() => { + expect( + TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length + ).to.be(1); + }, 10); + setTimeout(() => { + expect( + TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length + ).to.be(0); + notification.destroy(); + done(); + }, 1000); }); - expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, - 'test').length).to.be(1); - setTimeout(() => { - expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, - 'test').length).to.be(0); - notification.destroy(); - done(); - }, 1000); }); it('works with multi instance', (done) => { - const notification = Notification.newInstance(); - notification.notice({ - content:

1

, - duration: 0.1, - }); - notification.notice({ - content:

2

, - duration: 0.1, + Notification.newInstance({}, notification => { + notification.notice({ + content:

1

, + duration: 0.1, + }); + notification.notice({ + content:

2

, + duration: 0.1, + }); + setTimeout(() => { + expect( + TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length + ).to.be(2); + }, 10); + setTimeout(() => { + expect( + TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length + ).to.be(0); + notification.destroy(); + done(); + }, 1000); }); - expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, - 'test').length).to.be(2); - setTimeout(() => { - expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, - 'test').length).to.be(0); - notification.destroy(); - done(); - }, 1000); }); it('destroy works', () => { - const notification = Notification.newInstance(); - notification.notice({ - content:

222222

, - duration: 0.1, + Notification.newInstance({}, notification => { + notification.notice({ + content:

222222

, + duration: 0.1, + }); + setTimeout(() => { + expect( + TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length + ).to.be(1); + notification.destroy(); + expect(document.getElementById('test')).not.to.be.ok(); + }, 10); }); - expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, - 'test').length).to.be(1); - notification.destroy(); - expect(document.getElementById('test')).not.to.be.ok(); }); it('getContainer works', () => { - const notification = Notification.newInstance({ + Notification.newInstance({ getContainer: () => { const div = document.createElement('div'); div.className = 'rc'; document.body.appendChild(div); return div; }, + }, notification => { + notification.notice({ + content:

222222

, + duration: 1, + }); + expect(document.querySelectorAll('.rc').length).to.be(1); + notification.destroy(); }); - notification.notice({ - content:

222222

, - duration: 1, - }); - expect(document.querySelectorAll('.rc').length).to.be(1); - notification.destroy(); }); it('remove notify works', (done) => { - const notification = Notification.newInstance(); - const key = Date.now(); - const close = (k) => { - notification.removeNotice(k); - }; - notification.notice({ - content:

- -

, - key, - duration: null, - }); + Notification.newInstance({}, notification => { + const key = Date.now(); + const close = (k) => { + notification.removeNotice(k); + }; + notification.notice({ + content:

+ +

, + key, + duration: null, + }); - expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test') - .length).to.be(1); - const btnClose = document.getElementById('closeButton'); - TestUtils.Simulate.click(btnClose); - setTimeout(() => { - expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test') - .length).to.be(0); - notification.destroy(); - done(); - }, 1000); + setTimeout(() => { + expect( + TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length + ).to.be(1); + const btnClose = document.getElementById('closeButton'); + TestUtils.Simulate.click(btnClose); + setTimeout(() => { + expect( + TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length + ).to.be(0); + notification.destroy(); + done(); + }, 1000); + }, 10); + }); }); it('freeze notification layer when mouse over', (done) => { - const notification = Notification.newInstance(); - notification.notice({ - content:

freeze

, - duration: 0.3, - }); - expect(document.querySelectorAll('.freeze').length).to.be(1); - const content = document.getElementById('freeze'); - TestUtils.Simulate.mouseEnter(content); - setTimeout(() => { - expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze') - .length).to.be(1); - TestUtils.Simulate.mouseLeave(content); + Notification.newInstance({}, notification => { + notification.notice({ + content:

freeze

, + duration: 0.3, + }); setTimeout(() => { - expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze') - .length).to.be(0); - notification.destroy(); - done(); - }, 400); - }, 500); + expect(document.querySelectorAll('.freeze').length).to.be(1); + const content = document.getElementById('freeze'); + TestUtils.Simulate.mouseEnter(content); + setTimeout(() => { + expect( + TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze').length + ).to.be(1); + TestUtils.Simulate.mouseLeave(content); + setTimeout(() => { + expect( + TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze').length + ).to.be(0); + notification.destroy(); + done(); + }, 400); + }, 500); + }, 10); + }); + }); + + it('should work in lifecycle of React component', () => { + class Test extends React.Component { + componentDidMount() { + Notification.newInstance({}, notification => { + notification.notice({ + content: In lifecycle, + }); + }); + } + render() { + return null; + } + } + const container = document.createElement('div'); + document.body.appendChild(container); + expect(() => ReactDOM.render(, container)) + .to.not.throwException(); }); });