diff options
14 files changed, 1458 insertions, 2 deletions
diff --git a/web/src/js/__tests__/components/EventLog/EventListSpec.js b/web/src/js/__tests__/components/EventLog/EventListSpec.js new file mode 100644 index 00000000..4f14dfba --- /dev/null +++ b/web/src/js/__tests__/components/EventLog/EventListSpec.js @@ -0,0 +1,22 @@ +import React from 'react' +import EventLogList from '../../../components/EventLog/EventList' +import TestUtils from 'react-dom/test-utils' + +describe('EventList Component', () => { + let mockEventList = [ + { id: 1, level: 'info', message: 'foo' }, + { id: 2, level: 'error', message: 'bar' } + ], + eventLogList = TestUtils.renderIntoDocument(<EventLogList events={mockEventList}/>) + + it('should render correctly', () => { + expect(eventLogList.state).toMatchSnapshot() + expect(eventLogList.props).toMatchSnapshot() + }) + + it('should handle componentWillUnmount', () => { + window.removeEventListener = jest.fn() + eventLogList.componentWillUnmount() + expect(window.removeEventListener).toBeCalledWith('resize', eventLogList.onViewportUpdate) + }) +}) diff --git a/web/src/js/__tests__/components/EventLog/__snapshots__/EventListSpec.js.snap b/web/src/js/__tests__/components/EventLog/__snapshots__/EventListSpec.js.snap new file mode 100644 index 00000000..10bcb598 --- /dev/null +++ b/web/src/js/__tests__/components/EventLog/__snapshots__/EventListSpec.js.snap @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EventList Component should render correctly 1`] = ` +Object { + "vScroll": Object { + "end": 1, + "paddingBottom": 18, + "paddingTop": 0, + "start": 0, + }, +} +`; + +exports[`EventList Component should render correctly 2`] = ` +Object { + "events": Array [ + Object { + "id": 1, + "level": "info", + "message": "foo", + }, + Object { + "id": 2, + "level": "error", + "message": "bar", + }, + ], + "rowHeight": 18, +} +`; diff --git a/web/src/js/__tests__/components/FlowView/DetailsSpec.js b/web/src/js/__tests__/components/FlowView/DetailsSpec.js new file mode 100644 index 00000000..1b0192cf --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/DetailsSpec.js @@ -0,0 +1,50 @@ +import React from 'react' +import renderer from 'react-test-renderer' +import Details, { TimeStamp, ConnectionInfo, CertificateInfo, Timing } from '../../../components/FlowView/Details' +import { TFlow } from '../../ducks/tutils' + +let tflow = TFlow() + +describe('TimeStamp Component', () => { + it('should render correctly', () => { + let timestamp = renderer.create(<TimeStamp t={1483228800} deltaTo={1483228700} title="foo"/>), + tree = timestamp.toJSON() + expect(tree).toMatchSnapshot() + // without timestamp + timestamp = renderer.create(<TimeStamp/>) + tree = timestamp.toJSON() + expect(tree).toMatchSnapshot() + }) +}) + +describe('ConnectionInfo Component', () => { + it('should render correctly', () => { + let connectionInfo = renderer.create(<ConnectionInfo conn={tflow.client_conn}/>), + tree = connectionInfo.toJSON() + expect(tree).toMatchSnapshot() + }) +}) + +describe('CertificateInfo Component', () => { + it('should render correctly', () => { + let certificateInfo = renderer.create(<CertificateInfo flow={tflow}/>), + tree = certificateInfo.toJSON() + expect(tree).toMatchSnapshot() + }) +}) + +describe('Timing Component', () => { + it('should render correctly', () => { + let timing = renderer.create(<Timing flow={tflow}/>), + tree = timing.toJSON() + expect(tree).toMatchSnapshot() + }) +}) + +describe('Details Component', () => { + it('should render correctly', () => { + let details = renderer.create(<Details flow={tflow}/>), + tree = details.toJSON() + expect(tree).toMatchSnapshot() + }) +}) diff --git a/web/src/js/__tests__/components/FlowView/HeadersSpec.js b/web/src/js/__tests__/components/FlowView/HeadersSpec.js new file mode 100644 index 00000000..4ed93082 --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/HeadersSpec.js @@ -0,0 +1,132 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import renderer from 'react-test-renderer' +import TestUtils from 'react-dom/test-utils' +import Headers, { HeaderEditor } from '../../../components/FlowView/Headers' +import { Key } from '../../../utils' + +describe('HeaderEditor Component', () => { + + it('should render correctly', () => { + let headerEditor = renderer.create( + <HeaderEditor content="foo" onDone={jest.fn()}/>), + tree = headerEditor.toJSON() + expect(tree).toMatchSnapshot() + }) + + let doneFn = jest.fn(), + removeFn = jest.fn(), + tabFn = jest.fn(), + headerEditor = TestUtils.renderIntoDocument( + <HeaderEditor content="foo" onDone={doneFn} onRemove={removeFn} onTab={tabFn}/>) + + it('should handle focus', () => { + let focusFn = jest.fn() + ReactDOM.findDOMNode = jest.fn( node => { + return {focus: focusFn} + }) + headerEditor.focus() + expect(ReactDOM.findDOMNode).toBeCalledWith(headerEditor) + expect(focusFn).toBeCalled() + }) + + it('should handle keyDown', () => { + let mockEvent = { keyCode: Key.BACKSPACE }, + getRangeAt = jest.fn( s => { + return { startOffset: 0, endOffset: 0 } + }) + window.getSelection = jest.fn(selection => { + return { getRangeAt } + }) + // Backspace + headerEditor.onKeyDown(mockEvent) + expect(window.getSelection).toBeCalled() + expect(getRangeAt).toBeCalledWith(0) + expect(headerEditor.props.onRemove).toBeCalledWith(mockEvent) + // Enter & Tab + mockEvent.keyCode = Key.ENTER + headerEditor.onKeyDown(mockEvent) + expect(headerEditor.props.onTab).toBeCalledWith(mockEvent) + }) +}) + +describe('Headers Component', () => { + let changeFn = jest.fn(), + mockMessage = { headers: [['k1', 'v1'], ['k2', '']] } + it('should handle correctly', () => { + let headers = renderer.create(<Headers onChange={changeFn} message={mockMessage}/>), + tree = headers.toJSON() + expect(tree).toMatchSnapshot() + }) + + let headers = TestUtils.renderIntoDocument(<Headers onChange={changeFn} message={mockMessage}/>), + headerEditors = TestUtils.scryRenderedComponentsWithType(headers, HeaderEditor), + key1Editor = headerEditors[0], + value1Editor = headerEditors[1], + key2Editor = headerEditors[2], + value2Editor = headerEditors[3] + + it('should handle change on header name', () => { + key2Editor.props.onDone('') + expect(changeFn).toBeCalled() + expect(headers._nextSel).toEqual('0-value') + changeFn.mockClear() + }) + + it('should handle change on header value', () => { + value2Editor.props.onDone('') + expect(changeFn).toBeCalled() + expect(headers._nextSel).toEqual('0-value') + changeFn.mockClear() + }) + + let mockEvent = { preventDefault: jest.fn() } + it('should handle remove on header name', () => { + key2Editor.props.onRemove(mockEvent) + expect(mockEvent.preventDefault).toBeCalled() + mockEvent.preventDefault.mockClear() + }) + + it('should handle remove on header value', () => { + value2Editor.props.onRemove(mockEvent) + expect(mockEvent.preventDefault).toBeCalled() + mockEvent.preventDefault.mockClear() + }) + + it('should handle tab on header name', () => { + key1Editor.props.onTab(mockEvent) + expect(headers._nextSel).toEqual('0-value') + }) + + it('should handle tab on header value', () => { + value1Editor.props.onTab(mockEvent) + expect(headers._nextSel).toEqual('1-key') + + value2Editor.props.onTab(mockEvent) + expect(mockEvent.preventDefault).toBeCalled() + expect(headers._nextSel).toEqual('2-key') + }) + + it('should handle componentDidUpdate', () => { + headers._nextSel = '1-value' + headers.refs['1-value'] = { focus: jest.fn() } + headers.componentDidUpdate() + expect(headers.refs['1-value'].focus).toBeCalled() + expect(headers._nextSel).toEqual(undefined) + }) + + it('should handle edit', () => { + headers.refs['0-key'] = { focus: jest.fn() } + headers.edit() + expect(headers.refs['0-key'].focus).toBeCalled() + }) + + it('should not delete last row when handle remove', () => { + mockMessage = { headers: [['', '']] } + headers = TestUtils.renderIntoDocument(<Headers onChange={changeFn} message={mockMessage}/>) + headers.onChange(0, 0, '') + expect(changeFn).toBeCalledWith([['Name', 'Value']]) + + }) + +}) diff --git a/web/src/js/__tests__/components/FlowView/MessagesSpec.js b/web/src/js/__tests__/components/FlowView/MessagesSpec.js new file mode 100644 index 00000000..02db77e8 --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/MessagesSpec.js @@ -0,0 +1,143 @@ +jest.mock('../../../components/ContentView') +import React from 'react' +import renderer from 'react-test-renderer' +import TestUtils from 'react-dom/test-utils' +import { Request, Response, ErrorView } from '../../../components/FlowView/Messages' +import { Provider } from 'react-redux' +import { TFlow, TStore } from '../../ducks/tutils' +import { updateEdit } from '../../../ducks/ui/flow' +import { parseUrl } from '../../../flow/utils' +import ContentView from '../../../components/ContentView' +import ContentViewOptions from '../../../components/ContentView/ContentViewOptions' +import Headers from '../../../components/FlowView/Headers' +import ValueEditor from '../../../components/ValueEditor/ValueEditor' + +global.fetch = jest.fn() + +let tflow = new TFlow(), + store = TStore() +store.getState().ui.flow.modifiedFlow = false + +describe('Request Component', () => { + + afterEach(() => {store.clearActions()}) + + it('should render correctly', () => { + let provider = renderer.create( + <Provider store={store}> + <Request/> + </Provider> + ), + tree = provider.toJSON() + expect(tree).toMatchSnapshot() + }) + + let provider = TestUtils.renderIntoDocument( + <Provider store={store}> + <Request/> + </Provider>), + valueEditors = TestUtils.scryRenderedComponentsWithType(provider, ValueEditor) + + it('should handle done on flow request method', () => { + let valueEditor = valueEditors[0] + valueEditor.props.onDone('foo') + expect(store.getActions()).toEqual([updateEdit({ request: { method: 'foo' }})]) + }) + + it('should handle done on flow request url', () => { + let valueEditor = valueEditors[1], + url = 'http://foo/bar' + valueEditor.props.onDone(url) + expect(store.getActions()).toEqual([updateEdit({ request: { path: '', ...parseUrl(url)}})]) + }) + + it('should handle done on flow request http version', () => { + let valueEditor = valueEditors[2] + valueEditor.props.onDone('HTTP/9.9') + expect(store.getActions()).toEqual([updateEdit({ request: { http_version: 'HTTP/9.9' }})]) + }) + + it('should handle change on flow request header', () => { + let headers = TestUtils.findRenderedComponentWithType(provider, Headers) + headers.props.onChange('foo') + expect(store.getActions()).toEqual([updateEdit({ request: { headers: 'foo' }})]) + }) + + it('should handle change on flow request contentView', () => { + let contentView = TestUtils.findRenderedComponentWithType(provider, ContentView) + contentView.props.onContentChange('foo') + expect(store.getActions()).toEqual([updateEdit({ request: { content: 'foo' }})]) + }) + + it('should handle uploadContent on flow request ContentViewOptions', () => { + let contentViewOptions = TestUtils.findRenderedComponentWithType(provider, ContentViewOptions) + contentViewOptions.props.uploadContent('foo') + expect(fetch).toBeCalled() + fetch.mockClear() + }) +}) + +describe('Response Component', () => { + afterEach(() => {store.clearActions()}) + + it('should render correctly', () => { + let provider = renderer.create( + <Provider store={store}> + <Response/> + </Provider> + ), + tree = provider.toJSON() + expect(tree).toMatchSnapshot() + }) + + let provider = TestUtils.renderIntoDocument( + <Provider store={store}> + <Response/> + </Provider>), + valueEditors = TestUtils.scryRenderedComponentsWithType(provider, ValueEditor) + + it('should handle done on flow response http version', () => { + let valueEditor = valueEditors[0] + valueEditor.props.onDone('HTTP/9.9') + expect(store.getActions()).toEqual([updateEdit({ response: { http_version: 'HTTP/9.9' }})]) + }) + + it('should handle done on flow response status code', () => { + let valueEditor = valueEditors[1] + valueEditor.props.onDone('404') + expect(store.getActions()).toEqual([updateEdit({ response: { code: parseInt('404') }})]) + }) + + it('should handle done on flow response reason', () => { + let valueEdiotr = valueEditors[2] + valueEdiotr.props.onDone('foo') + expect(store.getActions()).toEqual([updateEdit( { response: { msg: 'foo' }})]) + }) + + it('should handle change on flow response headers', () => { + let headers = TestUtils.findRenderedComponentWithType(provider, Headers) + headers.props.onChange('foo') + expect(store.getActions()).toEqual([updateEdit( { response: { headers: 'foo' }})]) + }) + + it('should handle change on flow response ContentView', () => { + let contentView = TestUtils.findRenderedComponentWithType(provider, ContentView) + contentView.props.onContentChange('foo') + expect(store.getActions()).toEqual([updateEdit( { response: { content: 'foo' }})]) + }) + + it('should handle updateContent on flow response ContentViewOptions', () => { + let contentViewOptions = TestUtils.findRenderedComponentWithType(provider, ContentViewOptions) + contentViewOptions.props.uploadContent('foo') + expect(fetch).toBeCalled() + fetch.mockClear() + }) +}) + +describe('Error Component', () => { + it('should render correctly', () => { + let errorView = renderer.create(<ErrorView flow={tflow}/>), + tree = errorView.toJSON() + expect(tree).toMatchSnapshot() + }) +}) diff --git a/web/src/js/__tests__/components/FlowView/NavSpec.js b/web/src/js/__tests__/components/FlowView/NavSpec.js new file mode 100644 index 00000000..867e6f2c --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/NavSpec.js @@ -0,0 +1,38 @@ +import React from 'react' +import renderer from 'react-test-renderer' +import Nav, { NavAction } from '../../../components/FlowView/Nav' + +describe('Nav Component', () => { + let tabs = ['foo', 'bar'], + onSelectTab = jest.fn(), + nav = renderer.create(<Nav active='foo' tabs={tabs} onSelectTab={onSelectTab}/>), + tree = nav.toJSON() + + it('should render correctly', () => { + expect(tree).toMatchSnapshot() + }) + + it('should handle click', () => { + let mockEvent = { preventDefault: jest.fn() } + tree.children[0].props.onClick(mockEvent) + expect(mockEvent.preventDefault).toBeCalled() + expect(onSelectTab).toBeCalledWith('foo') + }) +}) + +describe('NavAction Component', () => { + let clickFn = jest.fn(), + navAction = renderer.create(<NavAction icon="foo" title="bar" onClick={clickFn}/>), + tree = navAction.toJSON() + + it('should render correctly', () => { + expect(tree).toMatchSnapshot() + }) + + it('should handle click', () => { + let mockEvent = { preventDefault: jest.fn() } + tree.props.onClick(mockEvent) + expect(mockEvent.preventDefault).toBeCalled() + expect(clickFn).toBeCalledWith(mockEvent) + }) +}) diff --git a/web/src/js/__tests__/components/FlowView/ToggleEditSpec.js b/web/src/js/__tests__/components/FlowView/ToggleEditSpec.js new file mode 100644 index 00000000..4578fdc8 --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/ToggleEditSpec.js @@ -0,0 +1,40 @@ +// jest.mock('../../../ducks/ui/flow') +import React from 'react' +import renderer from 'react-test-renderer' +import ToggleEdit from '../../../components/FlowView/ToggleEdit' +import { Provider } from 'react-redux' +import { startEdit, stopEdit } from '../../../ducks/ui/flow' +import { TFlow, TStore } from '../../ducks/tutils' + +let tflow = new TFlow() + +describe('ToggleEdit Component', () => { + let store = TStore(), + provider = renderer.create( + <Provider store={store}> + <ToggleEdit/> + </Provider>), + tree = provider.toJSON() + + afterEach(() => { store.clearActions() }) + + it('should render correctly', () => { + expect(tree).toMatchSnapshot() + }) + + it('should handle click on stopEdit', () => { + tree.children[0].props.onClick() + expect(store.getActions()).toEqual([stopEdit(tflow, true)]) + }) + + it('should handle click on startEdit', () => { + store.getState().ui.flow.modifiedFlow = false + let provider = renderer.create( + <Provider store={store}> + <ToggleEdit/> + </Provider>), + tree = provider.toJSON() + tree.children[0].props.onClick() + expect(store.getActions()).toEqual([startEdit(tflow)]) + }) +}) diff --git a/web/src/js/__tests__/components/FlowView/__snapshots__/DetailsSpec.js.snap b/web/src/js/__tests__/components/FlowView/__snapshots__/DetailsSpec.js.snap new file mode 100644 index 00000000..dcee1895 --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/__snapshots__/DetailsSpec.js.snap @@ -0,0 +1,274 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CertificateInfo Component should render correctly 1`] = `<div />`; + +exports[`ConnectionInfo Component should render correctly 1`] = ` +<table + className="connection-table" +> + <tbody> + <tr> + <td> + Address: + </td> + <td> + address:22 + </td> + </tr> + <tr> + <td> + <abbr + title="TLS Server Name Indication" + > + TLS SNI: + </abbr> + </td> + <td> + address + </td> + </tr> + </tbody> +</table> +`; + +exports[`Details Component should render correctly 1`] = ` +<section + className="detail" +> + <h4> + Client Connection + </h4> + <table + className="connection-table" + > + <tbody> + <tr> + <td> + Address: + </td> + <td> + address:22 + </td> + </tr> + <tr> + <td> + <abbr + title="TLS Server Name Indication" + > + TLS SNI: + </abbr> + </td> + <td> + address + </td> + </tr> + </tbody> + </table> + <h4> + Server Connection + </h4> + <table + className="connection-table" + > + <tbody> + <tr> + <td> + Address: + </td> + <td> + address:22 + </td> + </tr> + <tr> + <td> + <abbr + title="TLS Server Name Indication" + > + TLS SNI: + </abbr> + </td> + <td> + address + </td> + </tr> + </tbody> + </table> + <div /> + <div> + <h4> + Timing + </h4> + <table + className="timing-table" + > + <tbody> + <tr /> + <tr /> + <tr> + <td> + Server conn. initiated + : + </td> + <td> + 1970-01-01 00:00:01.000 + </td> + </tr> + <tr> + <td> + Client conn. established + : + </td> + <td> + 1970-01-01 00:00:01.000 + </td> + </tr> + <tr> + <td> + Server conn. TCP handshake + : + </td> + <td> + 1970-01-01 00:00:02.000 + </td> + </tr> + <tr> + <td> + Client conn. SSL handshake + : + </td> + <td> + 1970-01-01 00:00:02.000 + </td> + </tr> + <tr> + <td> + Server conn. SSL handshake + : + </td> + <td> + 1970-01-01 00:00:03.000 + </td> + </tr> + <tr> + <td> + First response byte + : + </td> + <td> + 2017-05-21 12:38:32.481 + </td> + </tr> + <tr> + <td> + Response complete + : + </td> + <td> + 2017-05-21 12:38:32.481 + </td> + </tr> + </tbody> + </table> + </div> +</section> +`; + +exports[`TimeStamp Component should render correctly 1`] = ` +<tr> + <td> + foo + : + </td> + <td> + 2017-01-01 00:00:00.000 + <span + className="text-muted" + > + ( + 2min + ) + </span> + </td> +</tr> +`; + +exports[`TimeStamp Component should render correctly 2`] = `<tr />`; + +exports[`Timing Component should render correctly 1`] = ` +<div> + <h4> + Timing + </h4> + <table + className="timing-table" + > + <tbody> + <tr /> + <tr /> + <tr> + <td> + Server conn. initiated + : + </td> + <td> + 1970-01-01 00:00:01.000 + </td> + </tr> + <tr> + <td> + Client conn. established + : + </td> + <td> + 1970-01-01 00:00:01.000 + </td> + </tr> + <tr> + <td> + Server conn. TCP handshake + : + </td> + <td> + 1970-01-01 00:00:02.000 + </td> + </tr> + <tr> + <td> + Client conn. SSL handshake + : + </td> + <td> + 1970-01-01 00:00:02.000 + </td> + </tr> + <tr> + <td> + Server conn. SSL handshake + : + </td> + <td> + 1970-01-01 00:00:03.000 + </td> + </tr> + <tr> + <td> + First response byte + : + </td> + <td> + 2017-05-21 12:38:32.481 + </td> + </tr> + <tr> + <td> + Response complete + : + </td> + <td> + 2017-05-21 12:38:32.481 + </td> + </tr> + </tbody> + </table> +</div> +`; diff --git a/web/src/js/__tests__/components/FlowView/__snapshots__/HeadersSpec.js.snap b/web/src/js/__tests__/components/FlowView/__snapshots__/HeadersSpec.js.snap new file mode 100644 index 00000000..5b5374dd --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/__snapshots__/HeadersSpec.js.snap @@ -0,0 +1,128 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`HeaderEditor Component should render correctly 1`] = ` +<div + className="inline-input editable" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "foo", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={0} +/> +`; + +exports[`Headers Component should handle correctly 1`] = ` +<table + className="header-table" +> + <tbody> + <tr> + <td + className="header-name" + > + <div + className="inline-input editable" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "k1", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={0} + /> + <span + className="header-colon" + > + : + </span> + </td> + <td + className="header-value" + > + <div + className="inline-input editable" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "v1", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={0} + /> + </td> + </tr> + <tr> + <td + className="header-name" + > + <div + className="inline-input editable" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "k2", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={0} + /> + <span + className="header-colon" + > + : + </span> + </td> + <td + className="header-value" + > + <div + className="inline-input editable" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={0} + /> + </td> + </tr> + </tbody> +</table> +`; diff --git a/web/src/js/__tests__/components/FlowView/__snapshots__/MessagesSpec.js.snap b/web/src/js/__tests__/components/FlowView/__snapshots__/MessagesSpec.js.snap new file mode 100644 index 00000000..c8290e45 --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/__snapshots__/MessagesSpec.js.snap @@ -0,0 +1,546 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Error Component should render correctly 1`] = ` +<section + className="error" +> + <div + className="alert alert-warning" + > + error + <div> + <small> + 2017-05-21 12:38:32.481 + </small> + </div> + </div> +</section> +`; + +exports[`Request Component should render correctly 1`] = ` +<section + className="request" +> + <article> + <div + className="edit-flow-container" + > + <a + className="edit-flow" + onClick={[Function]} + title="Edit Flow" + > + <i + className="fa fa-pencil" + /> + </a> + </div> + <div + className="first-line request-line" + > + <div> + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "GET", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + + <div + className="inline-input readonly has-success" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "http://address:22/path", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + + <div + className="inline-input readonly has-success" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "HTTP/1.1", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + </div> + </div> + <table + className="header-table" + > + <tbody> + <tr> + <td + className="header-name" + > + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "header", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + <span + className="header-colon" + > + : + </span> + </td> + <td + className="header-value" + > + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "qvalue", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + </td> + </tr> + <tr> + <td + className="header-name" + > + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "content-length", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + <span + className="header-colon" + > + : + </span> + </td> + <td + className="header-value" + > + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "7", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + </td> + </tr> + </tbody> + </table> + <hr /> + </article> + <footer> + <div + className="view-options" + > + <div + className="dropup pull-left" + > + <a + className="btn btn-default btn-xs" + href="#" + onClick={[Function]} + > + <span> + + <b> + View: + </b> + + auto + + <span + className="caret" + /> + + </span> + </a> + <ul + className="dropdown-menu" + role="menu" + > + <li> + + <a + href="#" + onClick={[Function]} + > + auto + </a> + + </li> + <li> + + <a + href="#" + onClick={[Function]} + > + raw + </a> + + </li> + <li> + + <a + href="#" + onClick={[Function]} + > + text + </a> + + </li> + </ul> + </div> + + <a + className="btn btn-default btn-xs" + href="/flows/d91165be-ca1f-4612-88a9-c0f8696f3e29/request/content" + title="Download the content of the flow." + > + <i + className="fa fa-download" + /> + </a> + + + <span> + foo + </span> + </div> + </footer> +</section> +`; + +exports[`Response Component should render correctly 1`] = ` +<section + className="response" +> + <article> + <div + className="edit-flow-container" + > + <a + className="edit-flow" + onClick={[Function]} + title="Edit Flow" + > + <i + className="fa fa-pencil" + /> + </a> + </div> + <div + className="first-line response-line" + > + <div + className="inline-input readonly has-success" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "HTTP/1.1", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + + <div + className="inline-input readonly has-success" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "200", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "OK", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + </div> + <table + className="header-table" + > + <tbody> + <tr> + <td + className="header-name" + > + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "header-response", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + <span + className="header-colon" + > + : + </span> + </td> + <td + className="header-value" + > + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "svalue", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + </td> + </tr> + <tr> + <td + className="header-name" + > + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "content-length", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + <span + className="header-colon" + > + : + </span> + </td> + <td + className="header-value" + > + <div + className="inline-input readonly" + contentEditable={undefined} + dangerouslySetInnerHTML={ + Object { + "__html": "7", + } + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onInput={[Function]} + onKeyDown={[Function]} + onMouseDown={[Function]} + onPaste={[Function]} + tabIndex={undefined} + /> + </td> + </tr> + </tbody> + </table> + <hr /> + </article> + <footer> + <div + className="view-options" + > + <div + className="dropup pull-left" + > + <a + className="btn btn-default btn-xs" + href="#" + onClick={[Function]} + > + <span> + + <b> + View: + </b> + + auto + + <span + className="caret" + /> + + </span> + </a> + <ul + className="dropdown-menu" + role="menu" + > + <li> + + <a + href="#" + onClick={[Function]} + > + auto + </a> + + </li> + <li> + + <a + href="#" + onClick={[Function]} + > + raw + </a> + + </li> + <li> + + <a + href="#" + onClick={[Function]} + > + text + </a> + + </li> + </ul> + </div> + + <a + className="btn btn-default btn-xs" + href="/flows/d91165be-ca1f-4612-88a9-c0f8696f3e29/response/content" + title="Download the content of the flow." + > + <i + className="fa fa-download" + /> + </a> + + + <span> + foo + </span> + </div> + </footer> +</section> +`; diff --git a/web/src/js/__tests__/components/FlowView/__snapshots__/NavSpec.js.snap b/web/src/js/__tests__/components/FlowView/__snapshots__/NavSpec.js.snap new file mode 100644 index 00000000..b1b1d3fd --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/__snapshots__/NavSpec.js.snap @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Nav Component should render correctly 1`] = ` +<nav + className="nav-tabs nav-tabs-sm" +> + <a + className="active" + href="#" + onClick={[Function]} + > + Foo + </a> + <a + className="" + href="#" + onClick={[Function]} + > + Bar + </a> +</nav> +`; + +exports[`NavAction Component should render correctly 1`] = ` +<a + className="nav-action" + href="#" + onClick={[Function]} + title="bar" +> + <i + className="fa fa-fw foo" + /> +</a> +`; diff --git a/web/src/js/__tests__/components/FlowView/__snapshots__/ToggleEditSpec.js.snap b/web/src/js/__tests__/components/FlowView/__snapshots__/ToggleEditSpec.js.snap new file mode 100644 index 00000000..5a4243a2 --- /dev/null +++ b/web/src/js/__tests__/components/FlowView/__snapshots__/ToggleEditSpec.js.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ToggleEdit Component should render correctly 1`] = ` +<div + className="edit-flow-container" +> + <a + className="edit-flow" + onClick={[Function]} + title="Finish Edit" + > + <i + className="fa fa-check" + /> + </a> +</div> +`; diff --git a/web/src/js/components/FlowView/Headers.jsx b/web/src/js/components/FlowView/Headers.jsx index 92e11465..76ca65b6 100644 --- a/web/src/js/components/FlowView/Headers.jsx +++ b/web/src/js/components/FlowView/Headers.jsx @@ -4,7 +4,7 @@ import ReactDOM from 'react-dom' import ValueEditor from '../ValueEditor/ValueEditor' import { Key } from '../../utils' -class HeaderEditor extends Component { +export class HeaderEditor extends Component { constructor(props) { super(props) diff --git a/web/src/js/components/FlowView/Nav.jsx b/web/src/js/components/FlowView/Nav.jsx index af5a879e..022f2f2b 100644 --- a/web/src/js/components/FlowView/Nav.jsx +++ b/web/src/js/components/FlowView/Nav.jsx @@ -2,6 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' import classnames from 'classnames' +import _ from 'lodash' NavAction.propTypes = { icon: PropTypes.string.isRequired, @@ -9,7 +10,7 @@ NavAction.propTypes = { onClick: PropTypes.func.isRequired, } -function NavAction({ icon, title, onClick }) { +export function NavAction({ icon, title, onClick }) { return ( <a title={title} href="#" |