Преглед на файлове

Merge branch 'dev' into carbon

Leopoldthecoder преди 8 години
родител
ревизия
e3aa5ac594

+ 16 - 0
CHANGELOG.en-US.md

@@ -1,5 +1,21 @@
 ## Changelog
 
+### 1.4.2
+
+*2017-08-09*
+
+- Fixed Select marking option of `value` equal to `0` as selected when the initial value is null and bound to an object-typed value, #6143
+- Fixed Step style issue when `status` is `error`, #6155 @wacky6
+- Fixed Cascader selecting parent item when moving mouse quickly after clicking a leaf item, #6199
+- Fixed Menu not hiding submenus when collapsed, #6200
+- Fixed status of the inner native input of Switch not syncing with the component, #6205 @wacky6
+- Fixed wrong button positioning of Slider after window is resized, #6263
+- Fixed Autocomplete not hiding dropdown menu on blur, #6256
+- Fixed hitting enter on jumper of Pagination not trigger page change event in IE, #6306 @qingdengyue
+- Fixed InputNumber style issue when its `size` is `large` or `small`, #6310 @JeremyWuuuuu
+- Fixed i18n failure for some texts in DatePicker, #6328
+- Fixed Slider value changing to minimum when its button is clicked, #6359
+
 ### 1.4.1
 
 *2017-07-28*

+ 15 - 0
CHANGELOG.zh-CN.md

@@ -1,5 +1,20 @@
 ## 更新日志
 
+### 1.4.2
+*2017-08-09*
+
+- 修复绑定值为对象类型时,初始值为 null 的 Select 会选中 value 为 `0` 的问题,#6143
+- 修复 `status` 为 `error` 的 Step 样式问题,#6155 @wacky6
+- 修复当 Cascader 的 `expand-trigger` 为 `hover` 时,点击选择条目后快速移动会再次选到父级元素的问题,#6199
+- 修复 Menu 在 collaspse 时不能收起子级菜单的问题,#6200
+- 修复 Switch 内部的原生 input 状态与组件不同步的问题,#6205 @wacky6
+- 修复 Slider 在 resize 窗口后滑块位置不准的问题,#6263
+- 修复 Autocomplete 在 blur 时不会收起下拉框的问题,#6256
+- 修复 Pagination 的 jumper 在 IE 下敲击回车无法触发翻页的问题,#6306 @qingdengyue
+- 修复 InputNumber 当 `size` 为 `large` 和 `small` 时的样式问题,#6310 @JeremyWuuuuu
+- 修复 DatePicker 的部分格式化文字 i18n 不生效的问题,#6328
+- 修复点击 Slider 的滑块会使其移动至起点的问题,#6359
+
 ### 1.4.1
 *2017-07-28*
 

+ 1 - 1
examples/docs/en-US/dropdown.md

@@ -221,6 +221,6 @@ Clicking each dropdown item fires an event whose parameter is assigned by each i
 ### Dropdown Menu Item Attributes
 | Attribute      | Description          | Type      | Accepted Values       | Default  |
 |-------------  |---------------- |---------------- |---------------------- |-------- |
-| command       | a command to be dispatched to Dropdown's `command` callback | string  |          —             |    —     |
+| command       | a command to be dispatched to Dropdown's `command` callback | string/number/object  |          —             |    —     |
 | disabled      | whether the item is disabled  | boolean  |          —             |    false     |
 | divided       | whether a divider is displayed  | boolean  |          —             |    false     |

+ 1 - 0
examples/docs/en-US/i18n.md

@@ -205,6 +205,7 @@ Currently Element ships with the following languages:
   <li>Afrikaans (af-ZA)</li>
   <li>Estonian (ee)</li>
   <li>Slovenian (sl)</li>
+  <li>Arabic (ar)</li>
 </ul>
 
 If your target language is not included, you are more than welcome to contribute: just add another language config [here](https://github.com/ElemeFE/element/tree/master/src/locale/lang) and create a pull request.

+ 1 - 1
examples/docs/zh-CN/dropdown.md

@@ -221,6 +221,6 @@
 ### Dropdown Menu Item Attributes
 | 参数          | 说明            | 类型            | 可选值                 | 默认值   |
 |-------------  |---------------- |---------------- |---------------------- |-------- |
-| command       | 指令     | string          | — | — |
+| command       | 指令     | string/number/object          | — | — |
 | disabled      | 禁用     | boolean          | — | false |
 | divided       | 显示分割线     | boolean          | — | false |

+ 1 - 0
examples/docs/zh-CN/i18n.md

@@ -217,6 +217,7 @@ ElementLocale.i18n((key, value) => i18n.t(key, value))
   <li>南非荷兰语(af-ZA)</li>
   <li>爱沙尼亚语(ee)</li>
   <li>斯洛文尼亚语(sl)</li>
+  <li>阿拉伯语(ar)</li>
 </ul>
 
 如果你需要使用其他的语言,欢迎贡献 PR:只需在 [这里](https://github.com/ElemeFE/element/tree/master/src/locale/lang) 添加一个语言配置文件即可。

+ 2 - 2
examples/index.tpl

@@ -9,8 +9,8 @@
   </head>
   <body>
     <div id="app"></div><% if (process.env.NODE_ENV === 'production') { %>
-    <script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.runtime.min.js"></script>
-    <script src="//cdnjs.cloudflare.com/ajax/libs/vue-router/2.1.1/vue-router.min.js"></script><% } %>
+    <script src="//cdn.jsdelivr.net/npm/vue@2.3.0/dist/vue.runtime.min.js"></script>
+    <script src="//cdn.jsdelivr.net/npm/vue-router@2.1.1/dist/vue-router.min.js"></script><% } %>
   </body>
   <% if (process.env.NODE_ENV === 'production') { %><script>
     (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){

+ 1 - 1
examples/versions.json

@@ -1 +1 @@
-{"1.0.9":"1.0","1.1.6":"1.1","1.2.9":"1.2","1.3.7":"1.3","1.4.1":"1.4"}
+{"1.0.9":"1.0","1.1.6":"1.1","1.2.9":"1.2","1.3.7":"1.3","1.4.2":"1.4"}

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "element-ui",
-  "version": "1.4.1",
+  "version": "1.4.2",
   "description": "A Component Library for Vue.js.",
   "main": "lib/element-ui.common.js",
   "files": [

+ 2 - 7
packages/autocomplete/src/autocomplete.vue

@@ -2,13 +2,7 @@
   <div class="el-autocomplete" v-clickoutside="close">
     <el-input
       ref="input"
-      :value="value"
-      :disabled="disabled"
-      :placeholder="placeholder"
-      :name="name"
-      :size="size"
-      :icon="icon"
-      :on-icon-click="onIconClick"
+      v-bind="$props"
       @compositionstart.native="handleComposition"
       @compositionupdate.native="handleComposition"
       @compositionend.native="handleComposition"
@@ -18,6 +12,7 @@
       @keydown.up.native.prevent="highlight(highlightedIndex - 1)"
       @keydown.down.native.prevent="highlight(highlightedIndex + 1)"
       @keydown.enter.native.prevent="handleKeyEnter"
+      @keydown.native.tab="close"
     >
       <template slot="prepend" v-if="$slots.prepend">
         <slot name="prepend"></slot>

+ 9 - 8
packages/date-picker/src/util/index.js

@@ -3,12 +3,13 @@ import { t } from 'element-ui/src/locale';
 
 const weeks = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
 const months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
-
-dateUtil.i18n = {
-  dayNamesShort: weeks.map(week => t(`el.datepicker.weeks.${ week }`)),
-  dayNames: weeks.map(week => t(`el.datepicker.weeks.${ week }`)),
-  monthNamesShort: months.map(month => t(`el.datepicker.months.${ month }`)),
-  monthNames: months.map((month, index) => t(`el.datepicker.month${ index + 1 }`))
+const getI18nSettings = () => {
+  return {
+    dayNamesShort: weeks.map(week => t(`el.datepicker.weeks.${ week }`)),
+    dayNames: weeks.map(week => t(`el.datepicker.weeks.${ week }`)),
+    monthNamesShort: months.map(month => t(`el.datepicker.months.${ month }`)),
+    monthNames: months.map((month, index) => t(`el.datepicker.month${ index + 1 }`))
+  };
 };
 
 const newArray = function(start, end) {
@@ -36,11 +37,11 @@ export const isDate = function(date) {
 export const formatDate = function(date, format) {
   date = toDate(date);
   if (!date) return '';
-  return dateUtil.format(date, format || 'yyyy-MM-dd');
+  return dateUtil.format(date, format || 'yyyy-MM-dd', getI18nSettings());
 };
 
 export const parseDate = function(string, format) {
-  return dateUtil.parse(string, format || 'yyyy-MM-dd');
+  return dateUtil.parse(string, format || 'yyyy-MM-dd', getI18nSettings());
 };
 
 export const getDayCountOfMonth = function(year, month) {

+ 1 - 1
packages/dropdown/src/dropdown-item.vue

@@ -19,7 +19,7 @@
     mixins: [Emitter],
 
     props: {
-      command: null,
+      command: {},
       disabled: Boolean,
       divided: Boolean
     },

+ 66 - 62
packages/menu/src/menu.vue

@@ -13,71 +13,9 @@
   </el-menu-collapse-transition>
 </template>
 <script>
-  import Vue from 'vue';
   import emitter from 'element-ui/src/mixins/emitter';
   import { addClass, removeClass, hasClass } from 'element-ui/src/utils/dom';
 
-  Vue.component('el-menu-collapse-transition', {
-    functional: true,
-    render(createElement, context) {
-      const data = {
-        props: {
-          mode: 'out-in'
-        },
-        on: {
-          beforeEnter(el) {
-            el.style.opacity = 0.2;
-          },
-
-          enter(el) {
-            addClass(el, 'el-opacity-transition');
-            el.style.opacity = 1;
-          },
-
-          afterEnter(el) {
-            removeClass(el, 'el-opacity-transition');
-            el.style.opacity = '';
-          },
-
-          beforeLeave(el) {
-            if (!el.dataset) el.dataset = {};
-
-            if (hasClass(el, 'el-menu--collapse')) {
-              removeClass(el, 'el-menu--collapse');
-              el.dataset.oldOverflow = el.style.overflow;
-              el.dataset.scrollWidth = el.scrollWidth;
-              addClass(el, 'el-menu--collapse');
-            }
-
-            el.style.width = el.scrollWidth + 'px';
-            el.style.overflow = 'hidden';
-          },
-
-          leave(el) {
-            if (!hasClass(el, 'el-menu--collapse')) {
-              addClass(el, 'horizontal-collapse-transition');
-              el.style.width = '64px';
-            } else {
-              addClass(el, 'horizontal-collapse-transition');
-              el.style.width = el.dataset.scrollWidth + 'px';
-            }
-          },
-
-          afterLeave(el) {
-            removeClass(el, 'horizontal-collapse-transition');
-            if (hasClass(el, 'el-menu--collapse')) {
-              el.style.width = el.dataset.scrollWidth + 'px';
-            } else {
-              el.style.width = '64px';
-            }
-            el.style.overflow = el.dataset.oldOverflow;
-          }
-        }
-      };
-      return createElement('transition', data, context.children);
-    }
-  });
-
   export default {
     name: 'ElMenu',
 
@@ -91,6 +29,69 @@
       };
     },
 
+    components: {
+      'el-menu-collapse-transition': {
+        functional: true,
+        render(createElement, context) {
+          const data = {
+            props: {
+              mode: 'out-in'
+            },
+            on: {
+              beforeEnter(el) {
+                el.style.opacity = 0.2;
+              },
+
+              enter(el) {
+                addClass(el, 'el-opacity-transition');
+                el.style.opacity = 1;
+              },
+
+              afterEnter(el) {
+                removeClass(el, 'el-opacity-transition');
+                el.style.opacity = '';
+              },
+
+              beforeLeave(el) {
+                if (!el.dataset) el.dataset = {};
+
+                if (hasClass(el, 'el-menu--collapse')) {
+                  removeClass(el, 'el-menu--collapse');
+                  el.dataset.oldOverflow = el.style.overflow;
+                  el.dataset.scrollWidth = el.scrollWidth;
+                  addClass(el, 'el-menu--collapse');
+                }
+
+                el.style.width = el.scrollWidth + 'px';
+                el.style.overflow = 'hidden';
+              },
+
+              leave(el) {
+                if (!hasClass(el, 'el-menu--collapse')) {
+                  addClass(el, 'horizontal-collapse-transition');
+                  el.style.width = '64px';
+                } else {
+                  addClass(el, 'horizontal-collapse-transition');
+                  el.style.width = el.dataset.scrollWidth + 'px';
+                }
+              },
+
+              afterLeave(el) {
+                removeClass(el, 'horizontal-collapse-transition');
+                if (hasClass(el, 'el-menu--collapse')) {
+                  el.style.width = el.dataset.scrollWidth + 'px';
+                } else {
+                  el.style.width = '64px';
+                }
+                el.style.overflow = el.dataset.oldOverflow;
+              }
+            }
+          };
+          return createElement('transition', data, context.children);
+        }
+      }
+    },
+
     props: {
       mode: {
         type: String,
@@ -134,6 +135,9 @@
       },
       defaultOpeneds(value) {
         this.openedMenus = value;
+      },
+      collapse(value) {
+        if (value) this.openedMenus = [];
       }
     },
     methods: {

+ 8 - 1
packages/pagination/src/pagination.js

@@ -189,7 +189,13 @@ export default {
         handleFocus(event) {
           this.oldValue = event.target.value;
         },
-
+        handleKeyUp(event) {
+          const key = event.key || '';
+          const keyCode = event.keyCode || '';
+          if ((key && key === 'Enter') || (keyCode && keyCode === 13)) {
+            this.handleChange({ target: event.target });
+          }
+        },
         handleChange({ target }) {
           this.$parent.internalCurrentPage = this.$parent.getValidCurrentPage(target.value);
           this.oldValue = null;
@@ -209,6 +215,7 @@ export default {
               domProps-value={ this.$parent.internalCurrentPage }
               on-change={ this.handleChange }
               on-focus={ this.handleFocus }
+              on-keyup={ this.handleKeyUp }
               number/>
             { this.t('el.pagination.pageClassifier') }
           </span>

+ 3 - 2
packages/slider/src/button.vue

@@ -141,10 +141,10 @@
           let diff = 0;
           if (this.vertical) {
             this.currentY = event.clientY;
-            diff = (this.startY - this.currentY) / this.$parent.$sliderSize * 100;
+            diff = (this.startY - this.currentY) / this.$parent.sliderSize * 100;
           } else {
             this.currentX = event.clientX;
-            diff = (this.currentX - this.startX) / this.$parent.$sliderSize * 100;
+            diff = (this.currentX - this.startX) / this.$parent.sliderSize * 100;
           }
           this.newPosition = this.startPosition + diff;
           this.setPosition(this.newPosition);
@@ -169,6 +169,7 @@
       },
 
       setPosition(newPosition) {
+        if (newPosition === null) return;
         if (newPosition < 0) {
           newPosition = 0;
         } else if (newPosition > 100) {

+ 16 - 8
packages/slider/src/main.vue

@@ -46,7 +46,6 @@
 <script type="text/babel">
   import ElInputNumber from 'element-ui/packages/input-number';
   import SliderButton from './button.vue';
-  import { getStyle } from 'element-ui/src/utils/dom';
   import Emitter from 'element-ui/src/mixins/emitter';
 
   export default {
@@ -115,7 +114,8 @@
         firstValue: null,
         secondValue: null,
         oldValue: null,
-        dragging: false
+        dragging: false,
+        sliderSize: 1
       };
     },
 
@@ -223,19 +223,21 @@
         if (this.disabled || this.dragging) return;
         if (this.vertical) {
           const sliderOffsetBottom = this.$refs.slider.getBoundingClientRect().bottom;
-          this.setPosition((sliderOffsetBottom - event.clientY) / this.$sliderSize * 100);
+          this.setPosition((sliderOffsetBottom - event.clientY) / this.sliderSize * 100);
         } else {
           const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
-          this.setPosition((event.clientX - sliderOffsetLeft) / this.$sliderSize * 100);
+          this.setPosition((event.clientX - sliderOffsetLeft) / this.sliderSize * 100);
+        }
+      },
+
+      resetSize() {
+        if (this.$refs.slider) {
+          this.sliderSize = this.$refs.slider[`client${ this.vertical ? 'Height' : 'Width' }`];
         }
       }
     },
 
     computed: {
-      $sliderSize() {
-        return parseInt(getStyle(this.$refs.slider, (this.vertical ? 'height' : 'width')), 10);
-      },
-
       stops() {
         if (this.step === 0) {
           process.env.NODE_ENV !== 'production' &&
@@ -320,6 +322,12 @@
         }
         this.oldValue = this.firstValue;
       }
+      this.resetSize();
+      window.addEventListener('resize', this.resetSize);
+    },
+
+    beforeDestroy() {
+      window.removeEventListener('resize', this.resetSize);
     }
   };
 </script>

+ 6 - 2
packages/steps/src/step.vue

@@ -80,6 +80,10 @@ export default {
     currentStatus() {
       return this.status || this.internalStatus;
     },
+    prevStatus() {
+      const prevStep = this.$parent.steps[this.index - 1];
+      return prevStep ? prevStep.currentStatus : 'wait';
+    },
     isLast: function() {
       const parent = this.$parent;
       return parent.steps[parent.steps.length - 1] === this;
@@ -114,7 +118,7 @@ export default {
 
       if (val > this.index) {
         this.internalStatus = this.$parent.finishStatus;
-      } else if (val === this.index) {
+      } else if (val === this.index && this.prevStatus !== 'error') {
         this.internalStatus = this.$parent.processStatus;
       } else {
         this.internalStatus = 'wait';
@@ -129,7 +133,7 @@ export default {
 
       style.transitionDelay = 150 * this.index + 'ms';
       if (status === this.$parent.processStatus) {
-        step = 50;
+        step = this.currentStatus !== 'error' ? 50 : 0;
       } else if (status === 'wait') {
         step = 0;
         style.transitionDelay = (-150 * this.index) + 'ms';

+ 2 - 1
packages/switch/src/component.vue

@@ -111,6 +111,7 @@
     },
     watch: {
       checked() {
+        this.$refs.input.checked = this.checked;
         if (this.onColor || this.offColor) {
           this.setBackgroundColor();
         }
@@ -118,8 +119,8 @@
     },
     methods: {
       handleChange(event) {
-        this.$emit('change', !this.checked ? this.onValue : this.offValue);
         this.$emit('input', !this.checked ? this.onValue : this.offValue);
+        this.$emit('change', !this.checked ? this.onValue : this.offValue);
         this.$nextTick(() => {
           // set input's checked property
           // in case parent refuses to change component's value

+ 5 - 0
packages/table/src/table.vue

@@ -4,6 +4,7 @@
       'el-table--fit': fit,
       'el-table--striped': stripe,
       'el-table--border': border,
+      'el-table--hidden': isHidden,
       'el-table--fluid-height': maxHeight,
       'el-table--enable-row-hover': !store.states.isComplex,
       'el-table--enable-row-transition': (store.states.data || []).length !== 0 && (store.states.data || []).length < 100
@@ -291,6 +292,9 @@
           } else if (this.shouldUpdateHeight) {
             this.layout.updateHeight();
           }
+          if (this.$el) {
+            this.isHidden = this.$el.clientWidth === 0;
+          }
         });
       }
     },
@@ -451,6 +455,7 @@
       return {
         store,
         layout,
+        isHidden: false,
         renderExpanded: null,
         resizeProxyVisible: false
       };

+ 1 - 1
packages/table/src/util.js

@@ -21,7 +21,7 @@ export const orderBy = function(array, sortKey, reverse, sortMethod) {
   if (typeof reverse === 'string') {
     reverse = reverse === 'descending' ? -1 : 1;
   }
-  if (!sortKey) {
+  if (!sortKey && !sortMethod) {
     return array;
   }
   const order = (reverse && reverse < 0) ? -1 : 1;

+ 1 - 1
packages/theme-default/package.json

@@ -1,6 +1,6 @@
 {
   "name": "element-theme-default",
-  "version": "1.4.1",
+  "version": "1.4.2",
   "description": "Element component default theme.",
   "main": "lib/index.css",
   "style": "lib/index.css",

+ 2 - 2
packages/theme-default/src/input-number.css

@@ -63,7 +63,7 @@
       width: 200px;
 
       & .el-input-number__increase, .el-input-number__decrease {
-        line-height: var(--input-large-height);
+        line-height: calc(var(--input-large-height) - 2);
         width: var(--input-large-height);
         font-size: var(--input-large-font-size);
       }
@@ -78,7 +78,7 @@
       width: 130px;
 
       & .el-input-number__increase, .el-input-number__decrease {
-        line-height: var(--input-small-height);
+        line-height: calc(var(--input-small-height) - 2);
         width: var(--input-small-height);
         font-size: var(--input-small-font-size);
       }

+ 4 - 0
packages/theme-default/src/table.css

@@ -146,6 +146,10 @@
       }
     }
 
+    @modifier hidden {
+      visibility: hidden;
+    }
+
     & th {
       background-color: var(--table-header-background);
       text-align: left;

+ 1 - 1
src/index.js

@@ -158,7 +158,7 @@ if (typeof window !== 'undefined' && window.Vue) {
 };
 
 module.exports = {
-  version: '1.4.1',
+  version: '1.4.2',
   locale: locale.use,
   i18n: locale.i18n,
   install,

+ 104 - 0
src/locale/lang/ar.js

@@ -0,0 +1,104 @@
+export default {
+  el: {
+    colorpicker: {
+      confirm: 'موافق',
+      clear: 'إزالة'
+    },
+    datepicker: {
+      now: 'الآن',
+      today: 'اليوم',
+      cancel: 'إلغاء',
+      clear: 'إزالة',
+      confirm: 'موافق',
+      selectDate: 'أختر التاريخ',
+      selectTime: 'أختر الوقت',
+      startDate: 'تاريخ البدء',
+      startTime: 'وقت البدء',
+      endDate: 'تاريخ الانتهاء',
+      endTime: 'وقت الانتهاء',
+      year: '',
+      month1: 'يناير',
+      month2: 'فبراير',
+      month3: 'مارس',
+      month4: 'ابريل',
+      month5: 'مايو',
+      month6: 'يونيو',
+      month7: 'يوليو',
+      month8: 'أغسطس',
+      month9: 'سبتمبر',
+      month10: 'أكتوبر',
+      month11: 'نوفمبر',
+      month12: 'ديسمبر',
+      week: 'أسبوع',
+      weeks: {
+        sun: 'الأحد',
+        mon: 'الأثنين',
+        tue: 'الثلاثاء',
+        wed: 'الأربعاء',
+        thu: 'الخميس',
+        fri: 'الجمعة',
+        sat: 'السبت'
+      },
+      months: {
+        jan: 'يناير',
+        feb: 'فبراير',
+        mar: 'مارس',
+        apr: 'أبريل',
+        may: 'مايو',
+        jun: 'يونيو',
+        jul: 'يوليو',
+        aug: 'أغسطس',
+        sep: 'سبتمبر',
+        oct: 'أكتوبر',
+        nov: 'نوفمبر',
+        dec: 'ديسمبر'
+      }
+    },
+    select: {
+      loading: 'جار التحميل',
+      noMatch: 'لايوجد بيانات مطابقة',
+      noData: 'لايوجد بيانات',
+      placeholder: 'أختر'
+    },
+    cascader: {
+      noMatch: 'لايوجد بيانات مطابقة',
+      loading: 'جار التحميل',
+      placeholder: 'أختر'
+    },
+    pagination: {
+      goto: 'أذهب إلى',
+      pagesize: '/صفحة',
+      total: 'الكل {total}',
+      pageClassifier: ''
+    },
+    messagebox: {
+      title: 'الرسالة',
+      confirm: 'موافق',
+      cancel: 'إلغاء',
+      error: 'مدخل غير صحيح'
+    },
+    upload: {
+      delete: 'حذف',
+      preview: 'عرض',
+      continue: 'إستمرار'
+    },
+    table: {
+      emptyText: 'لايوجد بيانات',
+      confirmFilter: 'تأكيد',
+      resetFilter: 'حذف',
+      clearFilter: 'الكل',
+      sumText: 'المجموع'
+    },
+    tree: {
+      emptyText: 'لايوجد بيانات'
+    },
+    transfer: {
+      noMatch: 'لايوجد بيانات مطابقة',
+      noData: 'لايوجد بيانات',
+      titles: ['قائمة 1', 'قائمة 2'], // to be translated
+      filterPlaceholder: 'ادخل كلمة', // to be translated
+      noCheckedFormat: '{total} عناصر', // to be translated
+      hasCheckedFormat: '{checked}/{total} مختار' // to be translated
+    }
+  }
+};

+ 18 - 0
test/unit/specs/steps.spec.js

@@ -122,4 +122,22 @@ describe('Steps', () => {
       done();
     });
   });
+
+  it('step:status=error', done => {
+    vm = createVue(`
+      <el-steps :active="2" process-status="process" finish-status="success" direction="horizontal">
+        <el-step title="step1"></el-step>
+        <el-step title="step2" status="error"></el-step>
+        <el-step title="step3"></el-step>
+      </el-steps>
+    `);
+
+    vm.$nextTick(_ => {
+      const errorLine = vm.$el.querySelector('.el-step:nth-child(2) .el-step__line-inner');
+      expect(errorLine.getBoundingClientRect().width).to.equal(0);
+      const nextStep = vm.$el.querySelector('.el-step:nth-child(3) .el-step__head');
+      expect(nextStep.classList.contains('is-wait')).to.equal(true);
+      done();
+    });
+  });
 });

+ 25 - 0
test/unit/specs/switch.spec.js

@@ -175,4 +175,29 @@ describe('Switch', () => {
       }, 10);
     }, 10);
   });
+
+  it('sets checkbox value', done => {
+    vm = createVue({
+      template: `
+        <div>
+          <el-switch v-model="value"></el-switch>
+        </div>
+      `,
+      data() {
+        return {
+          value: false
+        };
+      }
+    }, true);
+
+    vm.value = true;
+    setTimeout(() => {
+      expect(vm.$el.querySelector('input').checked).to.equal(true);
+      vm.value = false;
+      setTimeout(() => {
+        expect(vm.$el.querySelector('input').checked).to.equal(false);
+        done();
+      }, 10);
+    }, 10);
+  });
 });