diff --git a/03 Tests samples/src/components/MessageList/MessageList.less b/03 Tests samples/src/components/MessageList/MessageList.less index 5ad4777..bb1917a 100644 --- a/03 Tests samples/src/components/MessageList/MessageList.less +++ b/03 Tests samples/src/components/MessageList/MessageList.less @@ -5,7 +5,7 @@ .messages-table{ border: @tableBorder; - width: 80%; + width: 100%; border-collapse: collapse; td, th { border: @tableBorder; @@ -26,4 +26,15 @@ } } } -}; \ No newline at end of file +}; + +.messages-table-container { + width: 80%; + margin-left: 20px; +} + +.context-menu-info { + padding: 8px; + border: @tableBorder; + position: absolute; +} \ No newline at end of file diff --git a/03 Tests samples/src/components/MessageList/MessageList.test.tsx b/03 Tests samples/src/components/MessageList/MessageList.test.tsx index bb55fa5..ab06e79 100644 --- a/03 Tests samples/src/components/MessageList/MessageList.test.tsx +++ b/03 Tests samples/src/components/MessageList/MessageList.test.tsx @@ -1,47 +1,67 @@ import * as React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme'; import { configure } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; -import {MessageList} from './MessageList'; +import { MessageList } from './MessageList'; describe('Message List component test', () => { configure({ adapter: new Adapter() }); let component; - + const messages = [ + { + id: 1, + subject: 'Hello world', + body: 'Hello world', + }, + ]; + beforeEach(() => { - component = shallow(< MessageList messages={[]}/>); + component = shallow(); + }); + + afterEach(() => { + jest.clearAllMocks(); }); - it('should render a table', () =>{ + it('should render a table', () => { expect(component.find('table')).toHaveLength(1); }); - it('should render two th', () =>{ + it('should render two th', () => { expect(component.find('th')).toHaveLength(2); }); - it('should render a thead', () =>{ + it('should render a thead', () => { expect(component.find('thead')).toHaveLength(1); }); - it('should render a tbody', () =>{ + it('should render a tbody', () => { expect(component.find('tbody')).toHaveLength(1); }); - it('should render none td', () =>{ + it('should render none td', () => { expect(component.find('td')).toHaveLength(0); }); it('should render two td', () => { - let messages = [ - { - id: 1, - subject: 'Hello world', - body: 'Hello world' - } - ]; - component = shallow(< MessageList messages={messages}/>); + component = shallow(); expect(component.find('td')).toHaveLength(2); }); -}); \ No newline at end of file + + it('should alert mousedown on mouse down on the tr', () => { + jest.spyOn(window, 'alert').mockImplementation(() => {}); + component = shallow(); + const bodyMessages = component.find('tr').at(1); + bodyMessages.simulate('mousedown', { type: 'mousedown' }); + expect(window.alert).toBeCalledWith('mousedown'); + }); + + it('should alert mouseup on mouse up on the tr', () => { + jest.spyOn(window, 'alert').mockImplementation(() => {}); + component = shallow(); + const bodyMessages = component.find('tr').at(1); + bodyMessages.simulate('mouseup', { type: 'mouseup' }); + expect(window.alert).toBeCalledWith('mouseup'); + }); +}); diff --git a/03 Tests samples/src/components/MessageList/MessageList.tsx b/03 Tests samples/src/components/MessageList/MessageList.tsx index 58fd4ad..23c9054 100644 --- a/03 Tests samples/src/components/MessageList/MessageList.tsx +++ b/03 Tests samples/src/components/MessageList/MessageList.tsx @@ -3,24 +3,71 @@ import './MessageList.less'; import { Message } from '../../model'; interface MessageListProps { - messages: Message[], + messages: Message[]; } export const MessageList = (props: MessageListProps) => { - return ( - - - - - - - - {props.messages.map(message => { - return ( - - - ); - })} - -
SubjectBody
{message.subject}{message.body}
); + const [clickPosition, setClickPosition] = React.useState({ + clientX: 0, + clientY: 0, + }); + const [showContextMenu, setShowContextMenu] = React.useState(false); + + const handleContextMenu = (event: React.MouseEvent) => { + setClickPosition({ clientX: event.clientX, clientY: event.clientY }); + event.preventDefault(); + document.addEventListener('mousedown', handleClickAfterContextMenuOpen); + setShowContextMenu(true); + }; + + const handleOnMouse = (event: React.MouseEvent) => { + event.type === 'mousedown' ? alert('mousedown') : alert('mouseup'); + }; + + const handleClickAfterContextMenuOpen = (e: MouseEvent) => { + // Only if the left button is clicked - number 1 + // We need to perform this check since this method will also get called when right-clicking + if (e.which === 1) { + document.removeEventListener( + 'mousedown', + handleClickAfterContextMenuOpen + ); + setTimeout(() => setShowContextMenu(false), 100); + } + }; + + return ( +
+ + + + + + + + + {props.messages.map((message) => ( + + + + + ))} + +
SubjectBody
{message.subject}{message.body}
+ {showContextMenu && ( +
+
+ {`Context menu top-position:${clickPosition.clientY} left-position:${clickPosition.clientX}`} +
+
+ )} +
+ ); }; diff --git a/03 Tests samples/src/components/MessageList/onContextMenu.test.tsx b/03 Tests samples/src/components/MessageList/onContextMenu.test.tsx new file mode 100644 index 0000000..baf5319 --- /dev/null +++ b/03 Tests samples/src/components/MessageList/onContextMenu.test.tsx @@ -0,0 +1,40 @@ +import * as React from 'react'; +import { shallow } from 'enzyme'; +import { configure } from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; +import { MessageList } from './MessageList'; + +describe('Message List component test', () => { + configure({ adapter: new Adapter() }); + + let component; + + beforeEach(() => { + component = shallow(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should open a context-menu on right clicking on the table', () => { + const preventDefault = jest.fn(); + component + .find('div') + .at(0) + .simulate('contextMenu', { clientX: 969, clientY: 140, preventDefault }); + expect(component.find('.context-menu-info')).toHaveLength(1); + }); + // This test passes due to the setTimeout function, we should work over this. + it('should close context menu', () => { + const preventDefault = jest.fn(); + component + .find('div') + .at(0) + .simulate('contextMenu', { clientX: 969, clientY: 140, preventDefault }); + component.find('div').at(0).simulate('mousedown', { which: 1 }); + setTimeout(() => { + expect(component.find('.context-menu-info')).toHaveLength(0); + }, 150); + }); +});