diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4015763..b320288 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -61,6 +61,7 @@ Depreciate on next release
Known Issues
+- React-Router Warnings from using older version of react-router
- Icon 'safe-success' and 'safe-warn' is not showing [fix pr](https://github.com/weui/weui/pull/528)
#### 0.4.0 (2016-04-28)
diff --git a/example/app.js b/example/app.js
index aad8c42..78da097 100644
--- a/example/app.js
+++ b/example/app.js
@@ -6,35 +6,13 @@ import FastClick from 'fastclick';
import 'weui';
import "babel-polyfill";
-import Home from './pages/home/index';
-import Button from './pages/button/index';
-import List from './pages/list/index';
-import Input from './pages/input/index';
-import Toast from './pages/toast/index';
-import Dialog from './pages/dialog/index';
-import Progress from './pages/progress/index';
-import Msg from './pages/msg/index';
-import Article from './pages/article/index';
-import ActionSheet from './pages/actionsheet/index';
-import Icons from './pages/icons/index';
-import Panel from './pages/panel/index';
-import NavBar from './pages/tab/navbar';
-import NavBar2 from './pages/tab/navbar_auto';
-import TabBar from './pages/tab/tabbar';
-import TabBar2 from './pages/tab/tabbar_auto';
-import SearchBar from './pages/searchbar/index';
-import Gallery from './pages/gallery';
-import Uploader from './pages/uploader';
-import Flex from './pages/flex/index';
-import Footer from './pages/footer';
-import Grid from './pages/grid';
-import LoadMore from './pages/loadmore';
-import Preview from './pages/preview';
-import MsgSuccess from './pages/msg/success';
-import MsgFail from './pages/msg/fail';
-import TopTips from './pages/toptips';
-import Popup from './pages/popup';
-import Picker from './pages/picker';
+import Pages from './index';
+const { Home, Button, List, Input, Toast, Dialog, Progress, Msg, Article,
+ActionSheet, Icons, Panel, NavBar, NavBar2, TabBar, TabBar2, SearchBar, Gallery,
+Uploader, Flex, Footer, Grid, LoadMore, Preview, MsgSuccess, MsgFail, TopTips,
+Popup, Picker
+} = Pages;
+
class App extends React.Component {
render() {
diff --git a/src/components/actionsheet/actionsheet.js b/src/components/actionsheet/actionsheet.js
index e81e69f..2c40cd5 100644
--- a/src/components/actionsheet/actionsheet.js
+++ b/src/components/actionsheet/actionsheet.js
@@ -44,10 +44,19 @@ class ActionSheet extends Component {
menus: [],
actions: [],
show: false,
- autoDectect: true,
- onRequestClose: () => {}
+ autoDectect: true
};
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ isAndroid: isAndroid
+ }
+
+ this.handleMaskClick = this.handleMaskClick.bind(this)
+ }
+
renderMenuItem() {
return this.props.menus.map((menu, idx) => {
const {label, className, ...others} = menu;
@@ -76,6 +85,10 @@ class ActionSheet extends Component {
});
}
+ handleMaskClick(e){
+ if(this.props.onRequestClose) this.props.onRequestClose(e)
+ }
+
render() {
const {show, autoDectect, type, onRequestClose, menus, actions, ...others} = this.props;
const cls = classNames({
@@ -86,14 +99,14 @@ class ActionSheet extends Component {
let styleType = type ? type : 'ios';
if(!type && autoDectect){
- if(isAndroid) styleType = 'android';
+ if(this.state.isAndroid) styleType = 'android';
}
return (
-
+
{this.renderMenuItem()}
diff --git a/src/components/msg/msg.js b/src/components/msg/msg.js
index 3a088e9..e17b4e2 100644
--- a/src/components/msg/msg.js
+++ b/src/components/msg/msg.js
@@ -71,7 +71,7 @@ class Msg extends Component {
let elFooter = footer ? footer : ()=>false;
- if(!elFooter && (extraHref || extraText) ){
+ if(!elFooter() && (extraHref || extraText) ){
deprecationWarning('Msg extraHref/extraText', 'Msg footer')
elFooter = () => (
diff --git a/src/utils/deprecationWarning.js b/src/utils/deprecationWarning.js
index f6d33fb..ea9fb8f 100644
--- a/src/utils/deprecationWarning.js
+++ b/src/utils/deprecationWarning.js
@@ -3,6 +3,9 @@ import warning from 'warning';
const warned = {};
export default function deprecationWarning(oldname, newname, link) {
+ //avoid test warnings
+ if(typeof global.it === 'function') return;
+
const warnKey = `${oldname}\n${newname}`;
if (warned[warnKey]) {
return;
diff --git a/test/actionsheet.js b/test/actionsheet.js
new file mode 100644
index 0000000..f0ee573
--- /dev/null
+++ b/test/actionsheet.js
@@ -0,0 +1,119 @@
+/*global before*/
+import React from 'react';
+import { mount } from 'enzyme';
+import sinon from 'sinon';
+import assert from 'assert';
+import WeUI from '../src/index';
+var jsdom = require('jsdom');
+
+const {ActionSheet, Mask} = WeUI;
+const menus = [{
+ label: '拍照',
+ className: 'customClassName1'
+}, {
+ label: '从相册中选取',
+ className: 'customClassName2'
+}];
+const actions = [{
+ label: '取消',
+ className: 'customClassName'
+}, {
+ label: '确定'
+}];
+
+const androidUA = 'Mozilla/5.0 (Linux; U; Android 4.1.1; en-gb; Build/KLP) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30';
+const iosUA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 6_1_4 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B350 Safari/8536.25';
+
+describe('
', ()=> {
+ [androidUA, iosUA].map(userAgent=>{
+ ['ios', 'android', undefined].map(type => {
+ [undefined, null, true, false].map((show) => {
+ [null, sinon.spy()].map( onRequestClose => {
+ describe(`
`, ()=> {
+
+ before(() => {
+ global.document = jsdom.jsdom('', { userAgent: userAgent });
+ global.window = document.defaultView;
+ global.navigator = { userAgent: userAgent };
+ //console.log('test', window.navigator.userAgent)
+ });
+
+ const wrapper = mount(
+
+ );
+
+ const wrapperInstance = wrapper.instance();
+
+ it('should render ActionSheet', () => {
+ assert(wrapperInstance instanceof ActionSheet);
+ });
+
+ it(`should have a hidden when 'show' prop is false or undefined`, ()=> {
+ const mask = wrapper.find(Mask)
+ if (show) {
+ assert(mask.prop('style').display === 'block');
+ }
+ else {
+ assert(mask.prop('style').display === 'none');
+ }
+ });
+
+ it(`should have 'onRequestClose' event on Mask when 'show' prop is true`, ()=> {
+ if (show && onRequestClose) {
+ wrapper.find(Mask).simulate('click');
+ assert(onRequestClose.calledOnce === true);
+ }
+ });
+
+ it(`should have 'weui_actionsheet_toggle' class name when 'show' prop is true`, ()=> {
+ const actionSheet = wrapper.find('.weui-actionsheet');
+ if (show) {
+ assert(actionSheet.hasClass(`weui-actionsheet_toggle`));
+ }
+ else {
+ assert(!actionSheet.hasClass(`weui-actionsheet_toggle`));
+ }
+ });
+
+ it(`should render ${menus.length} menu items `, ()=> {
+ const menuItems = wrapper.find('.weui-actionsheet__menu').find('.weui-actionsheet__cell');
+ assert(menuItems.length === menus.length);
+
+ menuItems.map((menuItem, index)=> {
+ const menu = menus[index];
+ assert(menuItem.text() === menu.label);
+ menu.className && assert(menuItem.hasClass(menu.className));
+ });
+ });
+
+ it(`should render ${actions.length} actions`, ()=> {
+ const actionItems = wrapper.find('.weui-actionsheet__action').find('.weui-actionsheet__cell');
+ assert(actionItems.length === actions.length);
+
+ actionItems.map((actionItem, index)=> {
+ const action = actions[index];
+ assert(actionItem.text() === action.label);
+ action.className && assert(actionItem.hasClass(action.className));
+ });
+ });
+
+ if(type == 'android'){
+ it('should have "weui-skin_android" class on main wrapper', ()=> {
+ assert(wrapper.find('div').first().hasClass('weui-skin_android'));
+ });
+ }
+
+ if(!type && userAgent == androidUA) {
+ wrapper.setState({ isAndroid: true })
+ it(`when no type define, should detect android and have "weui-skin_android" class on main wrapper`, ()=> {
+ assert(wrapper.find('div').first().hasClass('weui-skin_android'));
+ });
+ }
+
+ });
+ })
+ });
+ })
+ })
+
+});
\ No newline at end of file
diff --git a/test/article.js b/test/article.js
new file mode 100644
index 0000000..9f40ecb
--- /dev/null
+++ b/test/article.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import assert from 'assert';
+import WeUI from '../src/index';
+
+const { Article } = WeUI;
+
+describe(' ', ()=> {
+ [undefined, null, '', 'custom_class'].map((clazz)=> {
+ describe(' ', ()=> {
+ const content = (
+
+
大标题
+
+ 章标题
+
+ 1.1 节标题
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
+ consequat. Duis aute
+
+
+ 1.2 节标题
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
+ proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+
+
+
+ );
+ const wrapper = shallow(
+
+ {content}
+
+ );
+
+ it('should render component', () => {
+ assert(wrapper.instance() instanceof Article);
+ });
+
+ it(`should have class name 'weui-article'`, ()=> {
+ assert(wrapper.hasClass(`weui-article`));
+ });
+
+ it(`should have custom class name ${clazz}`, ()=> {
+ if (clazz) {
+ assert(wrapper.hasClass(clazz));
+ }
+ });
+
+ it(`should have children`, ()=> {
+ assert(shallow(content).html() === wrapper.children().html());
+ });
+ });
+ })
+});
\ No newline at end of file
diff --git a/test/button.js b/test/button.js
index 5ff5859..4ff09f4 100644
--- a/test/button.js
+++ b/test/button.js
@@ -3,7 +3,33 @@ import { shallow } from 'enzyme';
import assert from 'assert';
import WeUI from '../src/index';
-const {Button} = WeUI;
+const { Button, PreviewButton } = WeUI;
+
+describe(' ', () => {
+ [true, false].map(primary => {
+ describe(`ok `, ()=>{
+ let wrapper = shallow(
+ ok
+ );
+
+ it('should have class with "weui-form-preview__btn"', ()=> {
+ assert(wrapper.hasClass('weui-form-preview__btn'));
+ });
+
+ it('should have class with "weui-form-preview__btn_default" when not primary', ()=> {
+ if (!primary) {
+ assert(wrapper.hasClass('weui-form-preview__btn_default'));
+ }
+ });
+
+ it('should have class with "weui-form-preview__btn_primary" when primary', ()=> {
+ if (primary) {
+ assert(wrapper.hasClass('weui-form-preview__btn_primary'));
+ }
+ });
+ })
+ })
+})
describe(' ', () => {
diff --git a/test/button_area.js b/test/button_area.js
new file mode 100644
index 0000000..b44fc6a
--- /dev/null
+++ b/test/button_area.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import assert from 'assert';
+import WeUI from '../src/index';
+
+const { ButtonArea, Button } = WeUI;
+
+describe(' ', () => {
+ [undefined, null, '', 'vertical', 'horizontal'].map((direction) => {
+ [undefined, null, '', 'custom_class'].map((className) => {
+ describe(` `, () => {
+ const child = 确定 ;
+ const wrapper = shallow(
+
+ {child}
+
+ );
+
+ it(`should render a component`, () => {
+ assert(wrapper.instance() instanceof ButtonArea);
+ });
+
+ it(`should have 'weui-btn-area' class name`, () => {
+ assert(wrapper.hasClass(`weui-btn-area`));
+ });
+
+ it(`should have custom class name ${className}`, () => {
+ if (className) {
+ assert(wrapper.hasClass(`${className}`));
+ }
+ });
+
+ it(`should have 'weui-btn-area_inline' when direction equal 'horizontal'`, () => {
+ if (direction === 'horizontal') {
+ assert(wrapper.hasClass(`weui-btn-area_inline`));
+ }
+ else {
+ assert(!wrapper.hasClass(`weui-btn-area_inline`));
+ }
+ });
+
+ it(`should have children`, () => {
+ assert(wrapper.find(Button).html() === shallow(child).html());
+ });
+ });
+ });
+ });
+});
diff --git a/test/icon.js b/test/icon.js
new file mode 100644
index 0000000..3a7e904
--- /dev/null
+++ b/test/icon.js
@@ -0,0 +1,61 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import assert from 'assert';
+import WeUI from '../src/index';
+
+const {Icon} = WeUI;
+
+describe('', ()=> {
+ [
+ 'success',
+ 'success-circle',
+ 'success-no-circle',
+ 'safe-success',
+ 'safe-warn',
+ 'info',
+ 'waiting',
+ 'waiting-circle',
+ 'circle',
+ 'warn',
+ 'download',
+ 'info-circle',
+ 'cancel',
+ //depreciate check
+ 'success_circle',
+ ].map((value) => {
+ ['small', 'large'].map((size) => {
+ describe(` `, ()=> {
+ const wrapper = shallow(
+
+ );
+
+ it(`should render component`, ()=> {
+ assert(wrapper.instance() instanceof Icon);
+ });
+
+ it(`should have class 'weui-icon-${value}'`, ()=> {
+ assert(wrapper.hasClass(`weui-icon-${value}`));
+ });
+
+ it(`should have 'weui-icon_msg' when size is large`, ()=> {
+ if (size === 'large') {
+ assert(wrapper.hasClass('weui-icon_msg'));
+ }
+ else {
+ assert(!wrapper.hasClass('weui-icon_msg'));
+ }
+ });
+ });
+ })
+ });
+
+ describe('loading', ()=> {
+ const wrapper = shallow(
+
+ );
+
+ it(`should have 'weui-loading' class name`, ()=> {
+ assert(wrapper.hasClass('weui-loading'));
+ });
+ })
+});
\ No newline at end of file
diff --git a/test/label.js b/test/label.js
new file mode 100644
index 0000000..1eff7ba
--- /dev/null
+++ b/test/label.js
@@ -0,0 +1,26 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import assert from 'assert';
+import WeUI from '../src/index';
+
+const {Label} = WeUI;
+
+describe(' ', ()=> {
+ [undefined, null, 'custom_class'].map(clazz => {
+ describe(` `, ()=> {
+ const wrapper = shallow(
+
+ );
+
+ it(`should render Label label component with weui_label class`, ()=> {
+ assert(wrapper.find('label').hasClass('weui-label'));
+ });
+
+ it(`should have custom class name ${clazz} when className is not null or empty`, ()=>{
+ if (clazz) {
+ assert(wrapper.find('label').hasClass(clazz));
+ }
+ });
+ });
+ });
+});
\ No newline at end of file
diff --git a/test/mask.js b/test/mask.js
new file mode 100644
index 0000000..22539f5
--- /dev/null
+++ b/test/mask.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import assert from 'assert';
+import WeUI from '../src/index';
+
+const {Mask} = WeUI;
+
+describe(' ', ()=> {
+ [true, false].map((transparent) => {
+ describe(` `, ()=> {
+ const wrapper = shallow(
+
+ );
+
+ it(`should render component`, ()=> {
+ assert(wrapper.instance() instanceof Mask);
+ });
+
+ it(`should transparent with transparent attribute`, ()=> {
+ if (transparent) {
+ assert(!wrapper.hasClass('weui-mask'));
+ assert(wrapper.hasClass('weui-mask_transparent'));
+ }
+ else {
+ assert(wrapper.hasClass('weui-mask'));
+ assert(!wrapper.hasClass('weui-mask_transparent'));
+ }
+ })
+ })
+ })
+});
\ No newline at end of file
diff --git a/test/msg.js b/test/msg.js
new file mode 100644
index 0000000..cf02372
--- /dev/null
+++ b/test/msg.js
@@ -0,0 +1,76 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import assert from 'assert';
+import WeUI from '../src/index';
+
+
+const {Msg, Icon, Button, Footer} = WeUI;
+
+describe(' ', ()=> {
+ const type = 'success';
+ const title = '成功';
+ const description = '感谢你的反馈';
+ const buttons = [{
+ type: 'primary',
+ label: '确定',
+ onClick: ()=>{
+ console.log('ok');
+ }
+ }];
+ const TestFooter = () => ;
+
+ it('should have footer for 0.4.x method', ()=> {
+ const $warningWrapper = shallow(
+
+ )
+
+ assert($warningWrapper.find(Footer).shallow().hasClass('weui-footer'));
+ //assert(spy.calledOnce());
+ });
+
+ ['success', 'info', 'waiting', 'warn'].map((type) => {
+ describe(` `, ()=> {
+ const wrapper = shallow(
+
+ );
+
+ it('should render component', ()=> {
+ assert(wrapper.instance() instanceof Msg);
+ assert(wrapper.hasClass('weui-msg'));
+ });
+
+ it(`should have `, ()=> {
+ const $icon = wrapper.find(Icon).shallow();
+ assert($icon.instance() instanceof Icon);
+ assert($icon.hasClass(`weui-icon-${type}`));
+ });
+
+ it(`should have title ${title}`, ()=> {
+ const $title = wrapper.find('.weui-msg__title');
+ assert($title.text() === title);
+ });
+
+ it(`should have description ${description}`, ()=> {
+ const $desc = wrapper.find('.weui-msg__desc');
+ assert($desc.text() === description);
+ });
+
+ it(`should render ${buttons.length} buttons`, ()=> {
+ const $buttons = wrapper.find(Button).shallow();
+ assert($buttons.length === buttons.length);
+ $buttons.map(($button, index) => {
+ assert($button.text() === buttons[index].label);
+ assert($button.prop('onClick') === buttons[index].onClick);
+ assert($button.hasClass(`weui-btn_${buttons[index].type}`));
+ });
+ });
+
+ it('should have ', ()=> {
+ const $footer = wrapper.find(Footer).shallow();
+ assert($footer.hasClass('weui-footer'));
+ });
+
+ });
+
+ });
+});
diff --git a/test/progress.js b/test/progress.js
new file mode 100644
index 0000000..854d0aa
--- /dev/null
+++ b/test/progress.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import { shallow, mount } from 'enzyme';
+import assert from 'assert';
+import sinon from 'sinon';
+import WeUI from '../src/index';
+
+const {Progress} = WeUI;
+
+describe(' ', ()=> {
+ [undefined, null, sinon.spy()].map((onClick) => {
+ [-10, 0, 10, 110].map((value) => {
+ [true, false].map(showCancel => {
+ describe(` `, () => {
+ let wrapper = shallow(
+
+ );
+
+ it(`should render component`, ()=> {
+ //not detecting for stateless component
+ //assert(wrapper.instance() instanceof Progress);
+ assert(wrapper.hasClass('weui-progress'));
+ });
+
+ it(`should have weui-progress__bar with .weui-progress__inner-bar element with width ${value}%`, ()=> {
+ const $barwrapper = wrapper.find('.weui-progress__bar');
+ const $bar = $barwrapper.find('.weui-progress__inner-bar');
+
+ assert($barwrapper.hasClass('weui-progress__bar'));
+
+
+ if (value < 0) {
+ assert($bar.prop('style').width === `0%`);
+ }
+ else if (value > 100) {
+ assert($bar.prop('style').width === `100%`);
+ }
+ else {
+ assert($bar.prop('style').width === `${value}%`);
+ }
+ });
+
+ it(`should have .weui-progress__opr element with 'onClick' attribute`, ()=> {
+ if (showCancel) {
+ assert(wrapper.find('.weui-progress__opr').length === 1);
+ if(onClick){
+ wrapper.find('.weui-progress__opr').simulate('click');
+ assert(onClick.called)
+ }
+ }
+ else {
+ assert(wrapper.find('.weui-progress__opr').length === 0);
+ }
+ });
+ });
+ })
+ });
+ });
+});
\ No newline at end of file
diff --git a/test/toast.js b/test/toast.js
new file mode 100644
index 0000000..f1d2dae
--- /dev/null
+++ b/test/toast.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import assert from 'assert';
+import WeUI from '../src/index';
+
+const {Toast, Mask, Icon} = WeUI;
+
+describe(' ', ()=> {
+ ['small', 'large'].map((iconSize) => {
+ [undefined, null, false, true].map((show) => {
+ ['toast', 'loading'].map((icon) => {
+ describe(` `, ()=> {
+ const body = '加载中...';
+ const wrapper = shallow(
+
+ {body}
+
+ );
+
+ it(`should render component`, () => {
+ assert(wrapper.instance() instanceof Toast);
+ assert(wrapper.find('.weui-toast'));
+ });
+
+ it(`should be hidden when 'show' attribute is false`, ()=> {
+ if (show) {
+ assert(wrapper.prop('style').display === 'block');
+ }
+ else {
+ assert(wrapper.prop('style').display === 'none');
+ }
+ });
+
+ it(`should have a transparent mask`, ()=> {
+ const mask = wrapper.find(Mask).shallow();
+ assert(mask.instance() instanceof Mask);
+ assert(!mask.hasClass('weui-mask'));
+ assert(mask.hasClass('weui-mask_transparent'));
+ });
+
+ it(`should have a icon`, ()=> {
+ const icon = wrapper.find(Icon).shallow();
+ assert(icon.instance() instanceof Icon);
+ });
+
+ it(`should have a icon with appropriate size`, ()=> {
+ const icon = wrapper.find(Icon).shallow();
+ assert(icon.instance() instanceof Icon);
+ });
+
+ it(`should have a icon with appropriate size: ${iconSize}`, ()=> {
+ const iconWrapper = wrapper.find(Icon).shallow();
+ //exclude loading case
+ if(icon != 'loading'){
+ if (iconSize === 'large') {
+ assert(iconWrapper.hasClass('weui-icon_msg'));
+ }
+ else {
+ assert(!iconWrapper.hasClass('weui-icon_msg'));
+ }
+ }
+ });
+
+ it(`should have 'weui-loading' and 'weui-icon_toast' class name when icon is 'loading'`, ()=> {
+ if (icon === 'loading') {
+ let $icon = wrapper.find(Icon).shallow()
+ assert($icon.hasClass('weui-loading'));
+ assert($icon.hasClass('weui-icon_toast'));
+ }
+ });
+
+ it(`should have body`, ()=> {
+ const $body = wrapper.find('.weui-toast_content');
+ assert($body.text() === body);
+ });
+ });
+ });
+ });
+ });
+});
\ No newline at end of file