import React from 'react'; import configureStore from 'redux-mock-store'; import {mount} from 'enzyme'; import VM from 'scratch-vm'; import vmListenerHOC from '../../../src/lib/vm-listener-hoc.jsx'; describe('VMListenerHOC', () => { const mockStore = configureStore(); let store; let vm; beforeEach(() => { vm = new VM(); store = mockStore({ scratchGui: { mode: {}, modals: {}, vm: vm } }); }); test('vm green flag event is bound to the passed in prop callback', () => { const Component = () => (
); const WrappedComponent = vmListenerHOC(Component); const onGreenFlag = jest.fn(); mount( ); expect(onGreenFlag).not.toHaveBeenCalled(); vm.emit('PROJECT_START'); expect(onGreenFlag).toHaveBeenCalled(); }); test('onGreenFlag is not passed to the children', () => { const Component = () => (
); const WrappedComponent = vmListenerHOC(Component); const wrapper = mount( ); const child = wrapper.find(Component); expect(child.props().onGreenFlag).toBeUndefined(); }); test('targetsUpdate event from vm triggers targets update action', () => { const Component = () => (
); const WrappedComponent = vmListenerHOC(Component); mount( ); const targetList = []; const editingTarget = 'id'; vm.emit('targetsUpdate', {targetList, editingTarget}); const actions = store.getActions(); expect(actions[0].type).toEqual('scratch-gui/targets/UPDATE_TARGET_LIST'); expect(actions[0].targets).toEqual(targetList); expect(actions[0].editingTarget).toEqual(editingTarget); }); test('targetsUpdate does not dispatch if the sound recorder is visible', () => { const Component = () => (
); const WrappedComponent = vmListenerHOC(Component); store = mockStore({ scratchGui: { mode: {}, modals: {soundRecorder: true}, vm: vm } }); mount( ); const targetList = []; const editingTarget = 'id'; vm.emit('targetsUpdate', {targetList, editingTarget}); const actions = store.getActions(); expect(actions.length).toEqual(0); }); test('PROJECT_CHANGED does dispatch if the sound recorder is visible', () => { const Component = () => (
); const WrappedComponent = vmListenerHOC(Component); store = mockStore({ scratchGui: { mode: {}, modals: {soundRecorder: true}, vm: vm } }); mount( ); vm.emit('PROJECT_CHANGED'); const actions = store.getActions(); expect(actions.length).toEqual(1); }); test('PROJECT_CHANGED does not dispatch if in fullscreen mode', () => { const Component = () => (
); const WrappedComponent = vmListenerHOC(Component); store = mockStore({ scratchGui: { mode: {isFullScreen: true}, modals: {soundRecorder: true}, vm: vm } }); mount( ); vm.emit('PROJECT_CHANGED'); const actions = store.getActions(); expect(actions.length).toEqual(0); }); test('keypresses go to the vm', () => { const Component = () => (
); const WrappedComponent = vmListenerHOC(Component); // Mock document.addEventListener so we can trigger keypresses manually // Cannot use the enzyme simulate method because that only works on synthetic events const eventTriggers = {}; document.addEventListener = jest.fn((event, cb) => { eventTriggers[event] = cb; }); vm.postIOData = jest.fn(); store = mockStore({ scratchGui: { mode: {isFullScreen: true}, modals: {soundRecorder: true}, vm: vm } }); mount( ); // keyboard events that do not target the document or body are ignored eventTriggers.keydown({key: 'A', target: null}); expect(vm.postIOData).not.toHaveBeenLastCalledWith('keyboard', {key: 'A', isDown: true}); // keydown/up with target as the document are sent to the vm via postIOData eventTriggers.keydown({key: 'A', target: document}); expect(vm.postIOData).toHaveBeenLastCalledWith('keyboard', {key: 'A', isDown: true}); eventTriggers.keyup({key: 'A', target: document}); expect(vm.postIOData).toHaveBeenLastCalledWith('keyboard', {key: 'A', isDown: false}); // When key is 'Dead' e.g. bluetooth keyboards on iOS, it sends keyCode instead // because the VM can process both named keys or keyCodes as the `key` property eventTriggers.keyup({key: 'Dead', keyCode: 10, target: document}); expect(vm.postIOData).toHaveBeenLastCalledWith('keyboard', {key: 10, isDown: false}); }); });