diff --git a/frontend/src/components/form/base/__tests__/ECheckbox.spec.js b/frontend/src/components/form/base/__tests__/ECheckbox.spec.js
index 465508eceb..6c366db8b1 100644
--- a/frontend/src/components/form/base/__tests__/ECheckbox.spec.js
+++ b/frontend/src/components/form/base/__tests__/ECheckbox.spec.js
@@ -12,53 +12,66 @@ Vue.use(formBaseComponents)
describe('An ECheckbox', () => {
let vuetify
- const mount = (options) => mountComponent(ECheckbox, { vuetify, ...options })
+ const mount = (options) => {
+ const app = Vue.component('App', {
+ components: { ECheckbox },
+ data: function () {
+ return {
+ data: null
+ }
+ },
+ template: `
+
+
+
+ `
+ })
+ return mountComponent(app, { vuetify, attachTo: document.body, ...options })
+ }
beforeEach(() => {
vuetify = new Vuetify()
})
test('looks like a checkbox', async () => {
const wrapper = mount()
- await wrapper.setProps({ vModel: false })
+ await wrapper.setData({ data: false })
expect(wrapper.element).toMatchSnapshot('unchecked')
- await wrapper.setProps({ vModel: true })
+ await wrapper.setData({ data: true })
expect(wrapper.element).toMatchSnapshot('checked')
})
test('is checked when initialized checked', () => {
const wrapper = mount({
- propsData: {
- vModel: true
+ data: function () {
+ return {
+ data: true
+ }
}
})
- expect(wrapper.find('input[type=checkbox]').element.getAttribute('vmodel')).toBe('true')
+ expect(wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked')).toBe('true')
})
test('updates checkbox when vModel changes', async () => {
const wrapper = mount()
- expect(wrapper.find('input[type=checkbox]').element.getAttribute('vmodel')).toBeNull()
+ await wrapper.setData({ data: false })
+ expect(wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked')).toBe('false')
- await wrapper.setProps({ vModel: true })
- expect(wrapper.find('input[type=checkbox]').element.getAttribute('vmodel')).toBe('true')
+ await wrapper.setData({ data: true })
+ expect(wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked')).toBe('true')
- await wrapper.setProps({ vModel: false })
- expect(wrapper.find('input[type=checkbox]').element.getAttribute('vmodel')).toBeNull()
+ await wrapper.setData({ data: false })
+ expect(wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked')).toBe('false')
})
test('updates vModel when user clicks on checkbox', async () => {
const wrapper = mount()
const input = wrapper.find('input')
- const change = jest.fn()
- wrapper.vm.$on('input', (event) => change(event))
-
await input.trigger('click')
- expect(change).toBeCalledTimes(1)
- expect(change).toBeCalledWith(true)
+ expect(wrapper.vm.data).toBe(true)
jest.resetAllMocks()
await input.trigger('click')
- expect(change).toBeCalledTimes(1)
- expect(change).toBeCalledWith(false)
+ expect(wrapper.vm.data).toBe(false)
})
})
diff --git a/frontend/src/components/form/base/__tests__/ESelect.spec.js b/frontend/src/components/form/base/__tests__/ESelect.spec.js
new file mode 100644
index 0000000000..df4bf898ab
--- /dev/null
+++ b/frontend/src/components/form/base/__tests__/ESelect.spec.js
@@ -0,0 +1,104 @@
+import Vue from 'vue'
+import Vuetify from 'vuetify'
+
+import { formBaseComponents } from '@/plugins'
+
+import { mount as mountComponent } from '@vue/test-utils'
+import ESelect from '../ESelect'
+
+Vue.use(Vuetify)
+Vue.use(formBaseComponents)
+
+describe('An ESelect', () => {
+ let vuetify
+
+ const FIRST_OPTION = {
+ value: 1,
+ text: 'firstOption'
+ }
+ const SECOND_OPTION = {
+ value: '2',
+ text: 'secondOption'
+ }
+ const THIRD_OPTION = {
+ value: { key: 'value', array: [1, 2, 3], nestedObject: { key: 'value' } },
+ text: 'thirdOption'
+ }
+ const selectValues = [
+ FIRST_OPTION,
+ SECOND_OPTION,
+ THIRD_OPTION
+ ]
+
+ const mount = (options) => {
+ const app = Vue.component('App', {
+ components: { ESelect },
+ data: function () {
+ return {
+ selectValues: selectValues,
+ data: null
+ }
+ },
+ template: `
+
+
+
+ `
+ })
+ return mountComponent(app, { vuetify, attachTo: document.body, ...options })
+ }
+
+ beforeEach(() => {
+ vuetify = new Vuetify()
+ })
+ test('looks like a dropdown', async () => {
+ const wrapper = mount()
+ expect(wrapper.element).toMatchSnapshot('no item selected')
+
+ await wrapper.find('.v-input__slot').trigger('click')
+ expect(wrapper.element).toMatchSnapshot('dropdown open')
+
+ await wrapper.findAll('[role="option"]').at(0).trigger('click')
+ expect(wrapper.element).toMatchSnapshot('dropdown closed with selected value')
+
+ await wrapper.find('.v-input__slot').trigger('click')
+ expect(wrapper.element).toMatchSnapshot('dropdown open with selected value')
+ })
+
+ test('update viewmodel with selected value', async () => {
+ const wrapper = mount()
+ expect(wrapper.vm.data).toBeNull()
+
+ await wrapper.find('.v-input__slot').trigger('click')
+ await wrapper.findAll('[role="option"]').at(0).trigger('click')
+ expect(wrapper.vm.data).toBe(FIRST_OPTION.value)
+
+ await wrapper.find('.v-input__slot').trigger('click')
+ await wrapper.findAll('[role="option"]').at(2).trigger('click')
+ expect(wrapper.vm.data).toBe(THIRD_OPTION.value)
+ })
+
+ test('update selected value with viewmodel', async () => {
+ const wrapper = mount()
+
+ await wrapper.setData({ data: SECOND_OPTION.value })
+ expect(wrapper.html()).toContain(SECOND_OPTION.text)
+ expect(wrapper.html()).not.toContain(FIRST_OPTION.text)
+
+ await wrapper.setData({ data: FIRST_OPTION.value })
+ expect(wrapper.html()).toContain(FIRST_OPTION.text)
+ expect(wrapper.html()).not.toContain(SECOND_OPTION.text)
+ })
+
+ test('update selected value after it was open', async () => {
+ const wrapper = mount()
+
+ await wrapper.find('.v-input__slot').trigger('click')
+ await wrapper.findAll('[role="option"]').at(0).trigger('click')
+ expect(wrapper.vm.data).toBe(FIRST_OPTION.value)
+
+ await wrapper.setData({ data: SECOND_OPTION.value })
+ expect(wrapper.findAll('[role="option"]').at(1).element.getAttribute('aria-selected')).toBe('true')
+ expect(wrapper.findAll('[role="option"]').at(0).element.getAttribute('aria-selected')).not.toBe('true')
+ })
+})
diff --git a/frontend/src/components/form/base/__tests__/ESwitch.spec.js b/frontend/src/components/form/base/__tests__/ESwitch.spec.js
new file mode 100644
index 0000000000..e01d07a1fd
--- /dev/null
+++ b/frontend/src/components/form/base/__tests__/ESwitch.spec.js
@@ -0,0 +1,102 @@
+import Vue from 'vue'
+import Vuetify from 'vuetify'
+
+import formBaseComponents from '@/plugins/formBaseComponents'
+
+import { mount as mountComponent } from '@vue/test-utils'
+import ESwitch from '@/components/form/base/ESwitch'
+import { touch } from '@/test/util'
+
+Vue.use(Vuetify)
+Vue.use(formBaseComponents)
+
+describe('An ESwitch', () => {
+ let vuetify
+
+ const mount = (options) => {
+ const app = Vue.component('App', {
+ components: { ESwitch },
+ data: function () {
+ return {
+ data: null
+ }
+ },
+ template: `
+
+
+
+ `
+ })
+ return mountComponent(app, { vuetify, attachTo: document.body, ...options })
+ }
+ beforeEach(() => {
+ vuetify = new Vuetify()
+ })
+ test('looks like a switch', async () => {
+ const wrapper = mount()
+ await wrapper.setData({ data: false })
+ expect(wrapper.element).toMatchSnapshot('unchecked')
+
+ await wrapper.setData({ data: true })
+ expect(wrapper.element).toMatchSnapshot('checked')
+ })
+
+ test('is checked when initialized checked', () => {
+ const wrapper = mount({
+ data: function () {
+ return {
+ data: true
+ }
+ }
+ })
+ expect(wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked')).toBe('true')
+ })
+
+ test('updates switch when vModel changes', async () => {
+ const wrapper = mount()
+ expect(wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked')).toBe('false')
+
+ await wrapper.setData({ data: true })
+ expect(wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked')).toBe('true')
+
+ await wrapper.setData({ data: false })
+ expect(wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked')).toBe('false')
+ })
+
+ test('updates vModel when user toggles with click', async () => {
+ const wrapper = mount()
+ const input = wrapper.find('input')
+
+ await input.trigger('click')
+ expect(wrapper.vm.data).toBe(true)
+
+ await input.trigger('click')
+ expect(wrapper.vm.data).toBe(false)
+ })
+
+ test('updates vModel when user toggles with touch swipe', async () => {
+ const wrapper = mount()
+
+ touch(wrapper.find('.v-input--selection-controls__ripple')).start(0, 0).end(20, 0)
+ expect(wrapper.vm.data).toBe(true)
+
+ jest.resetAllMocks()
+ touch(wrapper.find('.v-input--selection-controls__ripple')).start(0, 0).end(-20, 0)
+ expect(wrapper.vm.data).toBe(false)
+ })
+
+ test('updates vModel when user toggles with keys', async () => {
+ const wrapper = mount()
+ const input = wrapper.find('input')
+
+ input.trigger('keydown.right')
+ expect(wrapper.vm.data).toBe(true)
+
+ input.trigger('keydown.right')
+ expect(wrapper.vm.data).toBe(true)
+
+ jest.resetAllMocks()
+ input.trigger('keydown.left')
+ expect(wrapper.vm.data).toBe(false)
+ })
+})
diff --git a/frontend/src/components/form/base/__tests__/__snapshots__/ECheckbox.spec.js.snap b/frontend/src/components/form/base/__tests__/__snapshots__/ECheckbox.spec.js.snap
index f7abb6f855..ad1979f624 100644
--- a/frontend/src/components/form/base/__tests__/__snapshots__/ECheckbox.spec.js.snap
+++ b/frontend/src/components/form/base/__tests__/__snapshots__/ECheckbox.spec.js.snap
@@ -1,72 +1,79 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`An ECheckbox looks like a checkbox: checked 1`] = `
-
-
-
+
+
`;
exports[`An ECheckbox looks like a checkbox: unchecked 1`] = `
-
-
-
+
+
`;
diff --git a/frontend/src/components/form/base/__tests__/__snapshots__/ESelect.spec.js.snap b/frontend/src/components/form/base/__tests__/__snapshots__/ESelect.spec.js.snap
new file mode 100644
index 0000000000..1dcc4dbf2c
--- /dev/null
+++ b/frontend/src/components/form/base/__tests__/__snapshots__/ESelect.spec.js.snap
@@ -0,0 +1,462 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`An ESelect looks like a dropdown: dropdown closed with selected value 1`] = `
+
+`;
+
+exports[`An ESelect looks like a dropdown: dropdown open 1`] = `
+
+`;
+
+exports[`An ESelect looks like a dropdown: dropdown open with selected value 1`] = `
+
+`;
+
+exports[`An ESelect looks like a dropdown: no item selected 1`] = `
+
+`;
diff --git a/frontend/src/components/form/base/__tests__/__snapshots__/ESwitch.spec.js.snap b/frontend/src/components/form/base/__tests__/__snapshots__/ESwitch.spec.js.snap
new file mode 100644
index 0000000000..962be999cd
--- /dev/null
+++ b/frontend/src/components/form/base/__tests__/__snapshots__/ESwitch.spec.js.snap
@@ -0,0 +1,95 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`An ESwitch looks like a switch: checked 1`] = `
+
+`;
+
+exports[`An ESwitch looks like a switch: unchecked 1`] = `
+
+`;
diff --git a/frontend/src/test/util.js b/frontend/src/test/util.js
new file mode 100644
index 0000000000..a83a645d30
--- /dev/null
+++ b/frontend/src/test/util.js
@@ -0,0 +1,18 @@
+export function touch (element) {
+ const createTrigger = (eventName) => (clientX, clientY) => {
+ const touches = [{ clientX, clientY }]
+ const event = new Event(eventName)
+
+ event.touches = touches
+ event.changedTouches = touches
+ element.element.dispatchEvent(event)
+
+ return touch(element)
+ }
+
+ return {
+ start: createTrigger('touchstart'),
+ move: createTrigger('touchmove'),
+ end: createTrigger('touchend')
+ }
+}