diff --git a/scripts/__tests__/EventTest/EventMain.test.js b/scripts/__tests__/EventTest/EventMain.test.js new file mode 100644 index 00000000..1a3291c5 --- /dev/null +++ b/scripts/__tests__/EventTest/EventMain.test.js @@ -0,0 +1,131 @@ +import * as Horizon from '@cloudsop/horizon/index.ts'; +import * as LogUtils from '../jest/logUtils'; +import * as TestUtils from '../jest/testUtils'; + +describe('事件', () => { + it('根节点挂载全量事件', () => { + const App = () => { + return
; + } + Horizon.render(, container); + console.log(TestUtils.getEventListeners(container)); + }) + + it('事件捕获与冒泡', () => { + const App = () => { + return ( + <> +
LogUtils.log('div capture')} onClick={() => LogUtils.log('div bubble')}> +

LogUtils.log('p capture')} onClick={() => LogUtils.log('p bubble')}> +

+ + ); + } + Horizon.render(, container); + const a = container.querySelector('button'); + a.click(); + expect(LogUtils.getAndClear()).toEqual([ + // 从外到内先捕获再冒泡 + 'div capture', + 'p capture', + 'btn capture', + 'btn bubble', + 'p bubble', + 'div bubble' + ]); + }) + + it('returns 0', () => { + let keyCode = null; + const node = Horizon.render( + { + keyCode = e.keyCode; + }} + />, + container, + ); + node.dispatchEvent( + new KeyboardEvent('keypress', { + keyCode: 65, + bubbles: true, + cancelable: true, + }), + ); + expect(keyCode).toBe(65); + }); + + it('阻止事件冒泡', () => { + const App = () => { + return ( + <> +
LogUtils.log('div capture')} onClick={() => LogUtils.log('div bubble')}> +

LogUtils.log('p capture')} onClick={() => LogUtils.log('p bubble')}> +

+ + ); + } + Horizon.render(, container); + container.querySelector('button').click(); + + expect(LogUtils.getAndClear()).toEqual([ + // 到button时停止冒泡 + 'div capture', + 'p capture', + 'btn capture', + 'btn bubble' + ]); + }) + + it('阻止事件捕获', () => { + const App = () => { + return ( + <> +
TestUtils.stopBubbleOrCapture(e, 'div capture')} onClick={() => LogUtils.log('div bubble')}> +

LogUtils.log('p capture')} onClick={() => LogUtils.log('p bubble')}> +

+ + ); + } + Horizon.render(, container); + container.querySelector('button').click(); + + expect(LogUtils.getAndClear()).toEqual([ + // 阻止捕获,不再继续向下执行 + 'div capture' + ]); + }) + + it('阻止原生事件冒泡', () => { + const App = () => { + return ( +
+

+

+ ); + } + Horizon.render(, container); + container.querySelector('div').addEventListener('click', () => { + LogUtils.log('div bubble'); + }, false); + container.querySelector('p').addEventListener('click', () => { + LogUtils.log('p bubble'); + }, false); + container.querySelector('button').addEventListener('click', (e) => { + LogUtils.log('btn bubble'); + e.stopPropagation(); + }, false); + container.querySelector('button').click(); + expect(LogUtils.getAndClear()).toEqual([ + 'btn bubble' + ]); + }) +}) diff --git a/scripts/__tests__/EventTest/FocusEvent.test.js b/scripts/__tests__/EventTest/FocusEvent.test.js new file mode 100644 index 00000000..ee5e3c46 --- /dev/null +++ b/scripts/__tests__/EventTest/FocusEvent.test.js @@ -0,0 +1,46 @@ +import * as Horizon from '@cloudsop/horizon/index.ts'; +import * as LogUtils from '../jest/logUtils'; +import { act } from '../jest/customMatcher'; + +describe('合成焦点事件', () => { + + it('onFocus', () => { + const realNode = Horizon.render( + LogUtils.log(`onFocus: ${event.type}`)} + onFocusCapture={event => LogUtils.log(`onFocusCapture: ${event.type}`)} + />, container); + + realNode.dispatchEvent( + new FocusEvent('focusin', { + bubbles: true, + cancelable: false, + }), + ); + + expect(LogUtils.getAndClear()).toEqual([ + 'onFocusCapture: focus', + 'onFocus: focus', + ]); + }); + + it('onBlur', () => { + const realNode = Horizon.render( + LogUtils.log(`onBlur: ${event.type}`)} + onBlurCapture={event => LogUtils.log(`onBlurCapture: ${event.type}`)} + />, container); + + realNode.dispatchEvent( + new FocusEvent('focusout', { + bubbles: true, + cancelable: false, + }), + ); + + expect(LogUtils.getAndClear()).toEqual([ + 'onBlurCapture: blur', + 'onBlur: blur', + ]); + }) +}) \ No newline at end of file diff --git a/scripts/__tests__/EventTest/KeyboardEvent.test.js b/scripts/__tests__/EventTest/KeyboardEvent.test.js new file mode 100644 index 00000000..519cc9ce --- /dev/null +++ b/scripts/__tests__/EventTest/KeyboardEvent.test.js @@ -0,0 +1,179 @@ +import * as Horizon from '@cloudsop/horizon/index.ts'; +import * as LogUtils from '../jest/logUtils'; + +describe('Keyboard Event', () => { + + it('keydown,keypress,keyup的keycode,charcode', () => { + const node = Horizon.render( + { + LogUtils.log('onKeyUp: keycode: ' + e.keyCode + ',charcode: ' + e.charCode); + }} + onKeyDown={(e) => { + LogUtils.log('onKeyDown: keycode: ' + e.keyCode + ',charcode: ' + e.charCode) + }} + />, + container, + ); + node.dispatchEvent( + new KeyboardEvent('keydown', { + keyCode: 50, + code: 'Digit2', + bubbles: true, + cancelable: true, + }), + ); + node.dispatchEvent( + new KeyboardEvent('keyup', { + keyCode: 50, + code: 'Digit2', + bubbles: true, + cancelable: true, + }), + ); + + expect(LogUtils.getAndClear()).toEqual([ + 'onKeyDown: keycode: 50,charcode: 0', + 'onKeyUp: keycode: 50,charcode: 0' + ]); + }); + + it('keypress的keycode,charcode', () => { + const node = Horizon.render( + { + LogUtils.log('onKeyPress: keycode: ' + e.keyCode + ',charcode: ' + e.charCode); + }} + />, + container, + ); + node.dispatchEvent( + new KeyboardEvent('keypress', { + charCode: 50, + code: 'Digit2', + bubbles: true, + cancelable: true, + }), + ); + + expect(LogUtils.getAndClear()).toEqual([ + 'onKeyPress: keycode: 0,charcode: 50' + ]); + }); + + it('当charcode为13,且不设置keycode的时候', () => { + const node = Horizon.render( + { + LogUtils.log('onKeyPress: keycode: ' + e.keyCode + ',charcode: ' + e.charCode); + }} + />, + container, + ); + node.dispatchEvent( + new KeyboardEvent('keypress', { + charCode: 13, + bubbles: true, + cancelable: true, + }), + ); + expect(LogUtils.getAndClear()).toEqual([ + 'onKeyPress: keycode: 0,charcode: 13' + ]); + }); + + it('keydown,keypress,keyup的code', () => { + const node = Horizon.render( + { + LogUtils.log('onKeyUp: code: ' + e.code); + }} + onKeyPress={(e) => { + LogUtils.log('onKeyPress: code: ' + e.code); + }} + onKeyDown={(e) => { + LogUtils.log('onKeyDown: code: ' + e.code); + }} + />, + container, + ); + node.dispatchEvent( + new KeyboardEvent('keydown', { + code: 'Digit2', + bubbles: true, + cancelable: true, + }), + ); + + node.dispatchEvent( + new KeyboardEvent('keypress', { + keyCode: 50, + code: 'Digit2', + bubbles: true, + cancelable: true, + }), + ); + + node.dispatchEvent( + new KeyboardEvent('keyup', { + code: 'Digit2', + bubbles: true, + cancelable: true, + }), + ); + + expect(LogUtils.getAndClear()).toEqual([ + 'onKeyDown: code: Digit2', + 'onKeyPress: code: Digit2', + 'onKeyUp: code: Digit2' + ]); + }); + + it('可以执行preventDefault和 stopPropagation', () => { + const keyboardProcessing = e => { + expect(e.isDefaultPrevented()).toBe(false); + e.preventDefault(); + expect(e.isDefaultPrevented()).toBe(true); + + expect(e.isPropagationStopped()).toBe(false); + e.stopPropagation(); + expect(e.isPropagationStopped()).toBe(true); + LogUtils.log(e.type + ' handle'); + }; + const div = Horizon.render( +
, + container, + ); + + div.dispatchEvent( + new KeyboardEvent('keydown', { + keyCode: 40, + bubbles: true, + cancelable: true, + }), + ); + div.dispatchEvent( + new KeyboardEvent('keyup', { + keyCode: 40, + bubbles: true, + cancelable: true, + }), + ); + div.dispatchEvent( + new KeyboardEvent('keypress', { + charCode: 40, + bubbles: true, + cancelable: true, + }), + ); + expect(LogUtils.getAndClear()).toEqual([ + 'keydown handle', + 'keyup handle', + 'keypress handle' + ]); + }); +}); diff --git a/scripts/__tests__/EventTest/MouseEvent.test.js b/scripts/__tests__/EventTest/MouseEvent.test.js new file mode 100644 index 00000000..e5ffbae1 --- /dev/null +++ b/scripts/__tests__/EventTest/MouseEvent.test.js @@ -0,0 +1,160 @@ +import * as Horizon from '@cloudsop/horizon/index.ts'; +import * as LogUtils from '../jest/logUtils'; + +describe('MouseEvent Test', () => { + describe('onClick Test', () => { + it('绑定this', () => { + class App extends Horizon.Component { + constructor(props) { + super(props); + this.state = { + num: this.props.num, + price: this.props.price + }; + } + + setNum() { + this.setState( + { + num: this.state.num + 1 + } + ) + } + + setPrice = (e) => { + this.setState( + { + num: this.state.price + 1 + } + ) + } + + render() { + return ( + <> +

{this.state.num}

+

{this.state.price}

+ + + + ); + } + } + Horizon.render(, container); + expect(container.querySelector('p').innerHTML).toBe('0'); + expect(container.querySelector('#p').innerHTML).toBe('100'); + // 点击按钮触发num加1 + container.querySelector('button').click(); + expect(container.querySelector('p').innerHTML).toBe('1'); + + container.querySelector('#btn').click(); + expect(container.querySelector('p').innerHTML).toBe('101'); + }); + + it('点击触发', () => { + const handleClick = jest.fn(); + Horizon.render(, container) + container.querySelector('button').click(); + expect(handleClick).toHaveBeenCalledTimes(1); + for (let i = 0; i < 5; i++) { + container.querySelector('button').click(); + } + expect(handleClick).toHaveBeenCalledTimes(6); + }) + }) + + const test = (name, config) => { + const node = Horizon.render(config, container); + let event = new MouseEvent(name, { + relatedTarget: null, + bubbles: true, + screenX: 1 + }); + node.dispatchEvent(event); + + expect(LogUtils.getAndClear()).toEqual([ + `${name} capture`, + `${name} bubble` + ]); + + event = new MouseEvent(name, { + relatedTarget: null, + bubbles: true, + screenX: 2 + }); + node.dispatchEvent(event); + + // 再次触发新事件 + expect(LogUtils.getAndClear()).toEqual([ + `${name} capture`, + `${name} bubble` + ]); + } + + describe('合成鼠标事件', () => { + it('onMouseMove', () => { + const onMouseMove = () => { + LogUtils.log('mousemove bubble'); + }; + const onMouseMoveCapture = () => { + LogUtils.log('mousemove capture'); + }; + test('mousemove',
) + }); + + it('onMouseDown', () => { + const onMousedown = () => { + LogUtils.log('mousedown bubble'); + }; + const onMousedownCapture = () => { + LogUtils.log('mousedown capture'); + }; + test('mousedown',
) + }); + + it('onMouseUp', () => { + const onMouseUp = () => { + LogUtils.log('mouseup bubble'); + }; + const onMouseUpCapture = () => { + LogUtils.log('mouseup capture'); + }; + test('mouseup',
) + }); + + it('onMouseOut', () => { + const onMouseOut = () => { + LogUtils.log('mouseout bubble'); + }; + const onMouseOutCapture = () => { + LogUtils.log('mouseout capture'); + }; + test('mouseout',
) + }); + + it('onMouseOver', () => { + const onMouseOver = () => { + LogUtils.log('mouseover bubble'); + }; + const onMouseOverCapture = () => { + LogUtils.log('mouseover capture'); + }; + test('mouseover',
) + }); + }) +}) diff --git a/scripts/__tests__/EventTest/WheelEvent.test.js b/scripts/__tests__/EventTest/WheelEvent.test.js new file mode 100644 index 00000000..a0ebf933 --- /dev/null +++ b/scripts/__tests__/EventTest/WheelEvent.test.js @@ -0,0 +1,52 @@ +import * as Horizon from '@cloudsop/horizon/index.ts'; +import * as LogUtils from '../jest/logUtils'; + +describe('合成滚轮事件', () => { + it('onWheel', () => { + const realNode = Horizon.render( +
LogUtils.log(`onWheel: ${event.type}`)} + onWheelCapture={event => LogUtils.log(`onWheelCapture: ${event.type}`)} + />, container); + + realNode.dispatchEvent( + new MouseEvent('wheel', { + bubbles: true, + cancelable: false, + }), + ); + + expect(LogUtils.getAndClear()).toEqual([ + 'onWheelCapture: wheel', + 'onWheel: wheel' + ]); + }); + + it('可以执行preventDefault和 stopPropagation', () => { + const eventHandler = e => { + expect(e.isDefaultPrevented()).toBe(false); + e.preventDefault(); + expect(e.isDefaultPrevented()).toBe(true); + + expect(e.isPropagationStopped()).toBe(false); + e.stopPropagation(); + expect(e.isPropagationStopped()).toBe(true); + LogUtils.log(e.type + ' handle'); + }; + const realNode = Horizon.render( +
, + container + ); + + realNode.dispatchEvent( + new MouseEvent('wheel', { + bubbles: true, + cancelable: true, + }), + ); + expect(LogUtils.getAndClear()).toEqual([ + 'wheel handle' + ]); + }); + +}) \ No newline at end of file diff --git a/scripts/__tests__/jest/testUtils.js b/scripts/__tests__/jest/testUtils.js new file mode 100644 index 00000000..8bab93d9 --- /dev/null +++ b/scripts/__tests__/jest/testUtils.js @@ -0,0 +1,26 @@ +import { allDelegatedNativeEvents } from '../../../libs/horizon/src/event/EventCollection'; +import * as LogUtils from './logUtils'; + +export const stopBubbleOrCapture = (e, value) => { + LogUtils.log(value) + e.stopPropagation(); +}; + +export const getEventListeners = (dom) => { + let ret = true + let keyArray = []; + for (var key in dom) { + keyArray.push(key); + } + try { + allDelegatedNativeEvents.forEach(event => { + if (!keyArray.includes(event)) { + ret = false; + throw new Error('没有挂载全量事件'); + } + }) + } catch (error) { + + } + return ret; +}; \ No newline at end of file