diff --git a/packages/element-plus/index.ts b/packages/element-plus/index.ts index a4593edc8e..b0f2e7432d 100644 --- a/packages/element-plus/index.ts +++ b/packages/element-plus/index.ts @@ -12,6 +12,7 @@ import ElBreadcrumb from '@element-plus/breadcrumb' import ElIcon from '@element-plus/icon' import ElLink from '@element-plus/link' import ElRate from '@element-plus/rate' +import ElSwitch from '@element-plus/switch' export { ElAvatar, @@ -27,6 +28,7 @@ export { ElIcon, ElLink, ElRate, + ElSwitch, } export default function install(app: App): void { @@ -43,4 +45,5 @@ export default function install(app: App): void { ElIcon(app) ElLink(app) ElRate(app) + ElSwitch(app) } diff --git a/packages/element-plus/package.json b/packages/element-plus/package.json index 1146667154..6991972887 100644 --- a/packages/element-plus/package.json +++ b/packages/element-plus/package.json @@ -26,6 +26,9 @@ "@element-plus/progress": "^0.0.0", "@element-plus/tag": "^0.0.0", "@element-plus/time-line": "^0.0.0", - "@element-plus/rate": "^0.0.0" + "@element-plus/rate": "^0.0.0", + "@element-plus/breadcrumb": "^0.0.0", + "@element-plus/icon": "^0.0.0", + "@element-plus/switch": "^0.0.0" } } diff --git a/packages/switch/__tests__/switch.spec.ts b/packages/switch/__tests__/switch.spec.ts new file mode 100644 index 0000000000..fbea1055f4 --- /dev/null +++ b/packages/switch/__tests__/switch.spec.ts @@ -0,0 +1,231 @@ +import { mount } from '@vue/test-utils' +import Switch from '../src/index.vue' + +describe('Switch.vue', () => { + + test('create', () => { + const wrapper = mount(Switch, { + props: { + activeText: 'on', + inactiveText: 'off', + activeColor: '#0f0', + inactiveColor: '#f00', + width: 100, + }, + }) + const vm = wrapper.vm + const coreEl = vm.$el.querySelector('.el-switch__core') + expect(coreEl.style.backgroundColor).toEqual('rgb(255, 0, 0)') + expect(coreEl.style.width).toEqual('100px') + const leftLabelWrapper = wrapper.find('.el-switch__label--left span') + expect(leftLabelWrapper.text()).toEqual('off') + }) + + test('switch with icons', () => { + const wrapper = mount(Switch, { + props: { + activeIconClass: 'el-icon-check', + inactiveIconClass: 'el-icon-close', + }, + }) + + const iconWrapper = wrapper.find('.el-switch__label--left i') + expect(iconWrapper.classes('el-icon-close')).toBe(true) + }) + + test('value correctly update', async () => { + const wrapper = mount({ + components: { + 'el-switch': Switch, + }, + template: ` +
+ + +
+ `, + data() { + return { + value: true, + } + }, + }) + const vm = wrapper.vm + const coreEl = vm.$el.querySelector('.el-switch__core') + expect(coreEl.style.backgroundColor).toEqual('rgb(0, 255, 0)') + const coreWrapper = wrapper.find('.el-switch__core') + await coreWrapper.trigger('click') + expect(coreEl.style.backgroundColor).toEqual('rgb(255, 0, 0)') + expect(vm.value).toEqual(false) + await coreWrapper.trigger('click') + expect(vm.value).toEqual(true) + }) + + test('change event', async () => { + const wrapper = mount({ + components: { + 'el-switch': Switch, + }, + template: ` +
+ + +
+ `, + methods: { + handleChange(val) { + this.target = val + }, + }, + data() { + return { + target: 1, + value: true, + } + }, + }) + const vm = wrapper.vm + + expect(vm.target).toEqual(1) + const coreWrapper = wrapper.find('.el-switch__core') + await coreWrapper.trigger('click') + const switchWrapper = wrapper.findComponent(Switch) + expect(switchWrapper.emitted()['update:modelValue']).toBeTruthy() + expect(vm.target).toEqual(false) + }) + + test('disabled switch should not respond to user click', async () => { + const wrapper = mount({ + components: { + 'el-switch': Switch, + }, + template: ` +
+ +
+ `, + data() { + return { + value: true, + } + }, + }) + const vm = wrapper.vm + + expect(vm.value).toEqual(true) + const coreWrapper = wrapper.find('.el-switch__core') + await coreWrapper.trigger('click') + expect(vm.value).toEqual(true) + }) + + test('expand switch value', async () => { + const wrapper = mount({ + components: { + 'el-switch': Switch, + }, + template: ` +
+ +
+ `, + data() { + return { + value: '100', + onValue: '100', + offValue: '0', + } + }, + }) + const vm = wrapper.vm + + const coreWrapper = wrapper.find('.el-switch__core') + await coreWrapper.trigger('click') + expect(vm.value).toEqual('0') + await coreWrapper.trigger('click') + expect(vm.value).toEqual('100') + }) + + test('value is the single source of truth', async () => { + const wrapper = mount({ + components: { + 'el-switch': Switch, + }, + template: ` +
+ +
+ `, + }) + const vm = wrapper.vm + const coreWrapper = wrapper.find('.el-switch__core') + const switchWrapper = wrapper.findComponent(Switch) + const switchVm = switchWrapper.vm + const inputEl = vm.$el.querySelector('input') + + expect(switchVm.checked).toBe(true) + expect(switchWrapper.classes('is-checked')).toEqual(true) + expect(inputEl.checked).toEqual(true) + await coreWrapper.trigger('click') + expect(switchVm.checked).toBe(true) + expect(switchWrapper.classes('is-checked')).toEqual(true) + expect(inputEl.checked).toEqual(true) + }) + + test('model-value is the single source of truth', async () => { + const wrapper = mount({ + components: { + 'el-switch': Switch, + }, + template: ` +
+ +
+ `, + }) + const vm = wrapper.vm + const coreWrapper = wrapper.find('.el-switch__core') + const switchWrapper = wrapper.findComponent(Switch) + const switchVm = switchWrapper.vm + const inputEl = vm.$el.querySelector('input') + + expect(switchVm.checked).toBe(true) + expect(switchWrapper.classes('is-checked')).toEqual(true) + expect(inputEl.checked).toEqual(true) + await coreWrapper.trigger('click') + expect(switchVm.checked).toBe(true) + expect(switchWrapper.classes('is-checked')).toEqual(true) + expect(inputEl.checked).toEqual(true) + }) + + test('sets checkbox value', async () => { + const wrapper = mount({ + components: { + 'el-switch': Switch, + }, + template: ` +
+ +
+ `, + data() { + return { + value: false, + } + }, + }) + const vm = wrapper.vm + const inputEl = vm.$el.querySelector('input') + + vm.value = true + await vm.$nextTick() + expect(inputEl.checked).toEqual(true) + vm.value = false + await vm.$nextTick() + expect(inputEl.checked).toEqual(false) + }) +}) diff --git a/packages/switch/doc/basic.vue b/packages/switch/doc/basic.vue new file mode 100644 index 0000000000..8628f878a7 --- /dev/null +++ b/packages/switch/doc/basic.vue @@ -0,0 +1,28 @@ + + + + diff --git a/packages/switch/doc/index.stories.ts b/packages/switch/doc/index.stories.ts new file mode 100644 index 0000000000..40b8c46e67 --- /dev/null +++ b/packages/switch/doc/index.stories.ts @@ -0,0 +1,6 @@ +export { default as BasicUsage } from './basic.vue' + +export default { + title: 'Switch', +} + diff --git a/packages/switch/index.ts b/packages/switch/index.ts new file mode 100644 index 0000000000..d95865f1c6 --- /dev/null +++ b/packages/switch/index.ts @@ -0,0 +1,5 @@ +import { App } from 'vue' +import Switch from './src/index.vue' +export default (app: App): void => { + app.component(Switch.name, Switch) +} diff --git a/packages/switch/package.json b/packages/switch/package.json new file mode 100644 index 0000000000..30df452a02 --- /dev/null +++ b/packages/switch/package.json @@ -0,0 +1,12 @@ +{ + "name": "@element-plus/switch", + "version": "0.0.0", + "main": "dist/index.js", + "license": "MIT", + "peerDependencies": { + "vue": "^3.0.0-rc.1" + }, + "devDependencies": { + "@vue/test-utils": "^2.0.0-beta.0" + } +} diff --git a/packages/switch/src/index.vue b/packages/switch/src/index.vue new file mode 100644 index 0000000000..53d2ad8ce5 --- /dev/null +++ b/packages/switch/src/index.vue @@ -0,0 +1,224 @@ + + + +