-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(NcRichContenteditable): fix IME support
Signed-off-by: Grigorii K. Shartsev <me@shgk.me>
- Loading branch information
Showing
3 changed files
with
143 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
tests/unit/components/NcRichContenteditable/NcRichContenteditable.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import { mount } from '@vue/test-utils' | ||
import NcRichContenteditable from '../../../../src/components/NcRichContenteditable/NcRichContenteditable.vue' | ||
import Tribute from 'tributejs/dist/tribute.esm.js' | ||
|
||
// FIXME: find a way to use Tribute in JSDOM or test with e2e | ||
jest.mock('tributejs/dist/tribute.esm.js') | ||
Tribute.mockImplementation(() => ({ | ||
attach: jest.fn(), | ||
detach: jest.fn(), | ||
})) | ||
|
||
/** | ||
* Mount NcRichContentEditable | ||
* | ||
* @param {object} options mount options | ||
* @param {object} options.propsData mount options.propsData | ||
* @param {object} options.listeners mount options.listeners | ||
* @param {object} options.attrs mount options.attrs | ||
* @return {object} | ||
*/ | ||
function mountNcRichContenteditable({ propsData, listeners, attrs } = {}) { | ||
let currentValue = propsData?.value | ||
|
||
const wrapper = mount(NcRichContenteditable, { | ||
propsData: { | ||
value: currentValue, | ||
...propsData, | ||
}, | ||
listeners: { | ||
'update:value': ($event) => { | ||
currentValue = $event | ||
wrapper.setProps({ value: $event }) | ||
}, | ||
...listeners, | ||
}, | ||
attrs: { | ||
...attrs, | ||
}, | ||
attachTo: document.body, | ||
}) | ||
|
||
const getCurrentValue = () => currentValue | ||
|
||
const inputValue = async (newValue) => { | ||
wrapper.element.innerHTML += newValue | ||
await wrapper.trigger('input') | ||
} | ||
|
||
return { | ||
wrapper, | ||
getCurrentValue, | ||
inputValue, | ||
} | ||
} | ||
|
||
describe('NcRichContenteditable', () => { | ||
it('should update value during input', async () => { | ||
const { wrapper, inputValue } = mountNcRichContenteditable() | ||
const TEST_TEXT = 'Test Text' | ||
await inputValue('Test Text') | ||
expect(wrapper.emitted('update:value')).toBeDefined() | ||
expect(wrapper.emitted('update:value').at(-1)[0]).toBe(TEST_TEXT) | ||
}) | ||
|
||
it('should not emit "submit" during input', async () => { | ||
const { wrapper, inputValue } = mountNcRichContenteditable() | ||
await inputValue('Test Text') | ||
expect(wrapper.emitted('submit')).not.toBeDefined() | ||
}) | ||
|
||
it('should emit "paste" on past', async () => { | ||
const { wrapper } = mountNcRichContenteditable() | ||
await wrapper.trigger('paste', { clipboardData: { getData: () => 'PASTED_TEXT', files: [], items: {} } }) | ||
expect(wrapper.emitted('paste')).toBeDefined() | ||
expect(wrapper.emitted('paste')).toHaveLength(1) | ||
}) | ||
|
||
it('should emit "submit" on Enter', async () => { | ||
const { wrapper, inputValue } = mountNcRichContenteditable() | ||
|
||
await inputValue('Test Text') | ||
|
||
await wrapper.trigger('keydown', { keyCode: 13 }) // Enter | ||
|
||
expect(wrapper.emitted('submit')).toBeDefined() | ||
expect(wrapper.emitted('submit')).toHaveLength(1) | ||
}) | ||
|
||
it('should not emit "submit" on Enter during composition session', async () => { | ||
const { wrapper, inputValue } = mountNcRichContenteditable() | ||
|
||
await wrapper.trigger('compositionstart') | ||
await inputValue('猫') | ||
await wrapper.trigger('keydown', { keyCode: 13 }) // Enter | ||
await wrapper.trigger('compositionend') | ||
await inputValue(' - means "Cat"') | ||
await wrapper.trigger('keydown', { keyCode: 13 }) // Enter | ||
|
||
expect(wrapper.emitted('submit')).toBeDefined() | ||
expect(wrapper.emitted('submit')).toHaveLength(1) | ||
}) | ||
|
||
it('should proxy component events listeners to native event handlers', async () => { | ||
const handlers = { | ||
focus: jest.fn(), | ||
paste: jest.fn(), | ||
blur: jest.fn(), | ||
} | ||
const { wrapper } = mountNcRichContenteditable({ | ||
listeners: handlers, | ||
}) | ||
|
||
await wrapper.trigger('focus') | ||
await wrapper.trigger('paste', { clipboardData: { getData: () => 'PASTED_TEXT', files: [], items: {} } }) | ||
await wrapper.trigger('blur') | ||
|
||
expect(handlers.focus).toHaveBeenCalledTimes(1) | ||
expect(handlers.paste).toHaveBeenCalledTimes(1) | ||
expect(handlers.blur).toHaveBeenCalledTimes(1) | ||
}) | ||
}) |