mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2025-01-30 14:58:38 +00:00
Merge pull request #2337 from MatthewShao/jest-dev
[WIP][web] Add tests for UI components
This commit is contained in:
commit
a9e002af18
102
web/src/js/__tests__/components/FlowTable/FlowColumnsSpec.js
Normal file
102
web/src/js/__tests__/components/FlowTable/FlowColumnsSpec.js
Normal file
@ -0,0 +1,102 @@
|
||||
import React from 'react'
|
||||
import renderer from 'react-test-renderer'
|
||||
import * as Columns from '../../../components/FlowTable/FlowColumns'
|
||||
import { TFlow } from '../../ducks/tutils'
|
||||
|
||||
describe('FlowColumns Components', () => {
|
||||
|
||||
let tFlow = new TFlow()
|
||||
it('should render TLSColumn', () => {
|
||||
let tlsColumn = renderer.create(<Columns.TLSColumn flow={tFlow}/>),
|
||||
tree = tlsColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should render IconColumn', () => {
|
||||
let iconColumn = renderer.create(<Columns.IconColumn flow={tFlow}/>),
|
||||
tree = iconColumn.toJSON()
|
||||
// plain
|
||||
expect(tree).toMatchSnapshot()
|
||||
// not modified
|
||||
tFlow.response.status_code = 304
|
||||
iconColumn = renderer.create(<Columns.IconColumn flow={tFlow}/>)
|
||||
tree = iconColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
// redirect
|
||||
tFlow.response.status_code = 302
|
||||
iconColumn = renderer.create(<Columns.IconColumn flow={tFlow}/>)
|
||||
tree = iconColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
// image
|
||||
let imageFlow = new TFlow()
|
||||
imageFlow.response.headers = [['Content-Type', 'image/jpeg']]
|
||||
iconColumn = renderer.create(<Columns.IconColumn flow={imageFlow}/>)
|
||||
tree = iconColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
// javascript
|
||||
let jsFlow = new TFlow()
|
||||
jsFlow.response.headers = [['Content-Type', 'application/x-javascript']]
|
||||
iconColumn = renderer.create(<Columns.IconColumn flow={jsFlow}/>)
|
||||
tree = iconColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
// css
|
||||
let cssFlow = new TFlow()
|
||||
cssFlow.response.headers = [['Content-Type', 'text/css']]
|
||||
iconColumn = renderer.create(<Columns.IconColumn flow={cssFlow}/>)
|
||||
tree = iconColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
// default
|
||||
let fooFlow = new TFlow()
|
||||
fooFlow.response.headers = [['Content-Type', 'foo']]
|
||||
iconColumn = renderer.create(<Columns.IconColumn flow={fooFlow}/>)
|
||||
tree = iconColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
// no response
|
||||
tFlow.response = null
|
||||
iconColumn = renderer.create(<Columns.IconColumn flow={tFlow}/>)
|
||||
tree = iconColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should render pathColumn', () => {
|
||||
let pathColumn = renderer.create(<Columns.PathColumn flow={tFlow}/>),
|
||||
tree = pathColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
|
||||
tFlow.error.msg = 'Connection killed'
|
||||
tFlow.intercepted = true
|
||||
pathColumn = renderer.create(<Columns.PathColumn flow={tFlow}/>)
|
||||
tree = pathColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should render MethodColumn', () => {
|
||||
let methodColumn =renderer.create(<Columns.MethodColumn flow={tFlow}/>),
|
||||
tree = methodColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should render StatusColumn', () => {
|
||||
let statusColumn = renderer.create(<Columns.StatusColumn flow={tFlow}/>),
|
||||
tree = statusColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should render SizeColumn', () => {
|
||||
tFlow = new TFlow()
|
||||
let sizeColumn = renderer.create(<Columns.SizeColumn flow={tFlow}/>),
|
||||
tree = sizeColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should render TimeColumn', () => {
|
||||
let timeColumn = renderer.create(<Columns.TimeColumn flow={tFlow}/>),
|
||||
tree = timeColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
|
||||
tFlow.response = null
|
||||
timeColumn = renderer.create(<Columns.TimeColumn flow={tFlow}/>),
|
||||
tree = timeColumn.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
})
|
@ -0,0 +1,156 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`FlowColumns Components should render IconColumn 1`] = `
|
||||
<td
|
||||
className="col-icon"
|
||||
>
|
||||
<div
|
||||
className="resource-icon resource-icon-document"
|
||||
/>
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render IconColumn 2`] = `
|
||||
<td
|
||||
className="col-icon"
|
||||
>
|
||||
<div
|
||||
className="resource-icon resource-icon-not-modified"
|
||||
/>
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render IconColumn 3`] = `
|
||||
<td
|
||||
className="col-icon"
|
||||
>
|
||||
<div
|
||||
className="resource-icon resource-icon-redirect"
|
||||
/>
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render IconColumn 4`] = `
|
||||
<td
|
||||
className="col-icon"
|
||||
>
|
||||
<div
|
||||
className="resource-icon resource-icon-image"
|
||||
/>
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render IconColumn 5`] = `
|
||||
<td
|
||||
className="col-icon"
|
||||
>
|
||||
<div
|
||||
className="resource-icon resource-icon-js"
|
||||
/>
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render IconColumn 6`] = `
|
||||
<td
|
||||
className="col-icon"
|
||||
>
|
||||
<div
|
||||
className="resource-icon resource-icon-css"
|
||||
/>
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render IconColumn 7`] = `
|
||||
<td
|
||||
className="col-icon"
|
||||
>
|
||||
<div
|
||||
className="resource-icon resource-icon-plain"
|
||||
/>
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render IconColumn 8`] = `
|
||||
<td
|
||||
className="col-icon"
|
||||
>
|
||||
<div
|
||||
className="resource-icon resource-icon-plain"
|
||||
/>
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render MethodColumn 1`] = `
|
||||
<td
|
||||
className="col-method"
|
||||
>
|
||||
GET
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render SizeColumn 1`] = `
|
||||
<td
|
||||
className="col-size"
|
||||
>
|
||||
100b
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render StatusColumn 1`] = `
|
||||
<td
|
||||
className="col-status"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render TLSColumn 1`] = `
|
||||
<td
|
||||
className="col-tls col-tls-http"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render TimeColumn 1`] = `
|
||||
<td
|
||||
className="col-time"
|
||||
>
|
||||
2min
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render TimeColumn 2`] = `
|
||||
<td
|
||||
className="col-time"
|
||||
>
|
||||
...
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render pathColumn 1`] = `
|
||||
<td
|
||||
className="col-path"
|
||||
>
|
||||
<i
|
||||
className="fa fa-fw fa-repeat pull-right"
|
||||
/>
|
||||
<i
|
||||
className="fa fa-fw fa-exclamation pull-right"
|
||||
/>
|
||||
http://undefined:undefinedundefined
|
||||
</td>
|
||||
`;
|
||||
|
||||
exports[`FlowColumns Components should render pathColumn 2`] = `
|
||||
<td
|
||||
className="col-path"
|
||||
>
|
||||
<i
|
||||
className="fa fa-fw fa-repeat pull-right"
|
||||
/>
|
||||
<i
|
||||
className="fa fa-fw fa-pause pull-right"
|
||||
/>
|
||||
<i
|
||||
className="fa fa-fw fa-times pull-right"
|
||||
/>
|
||||
http://undefined:undefinedundefined
|
||||
</td>
|
||||
`;
|
@ -0,0 +1,47 @@
|
||||
import React from 'react'
|
||||
import renderer from 'react-test-renderer'
|
||||
import TestUtils from 'react-dom/test-utils'
|
||||
import ValidateEditor from '../../../components/ValueEditor/ValidateEditor'
|
||||
|
||||
describe('ValidateEditor Component', () => {
|
||||
let validateFn = jest.fn( content => content.length == 3),
|
||||
doneFn = jest.fn()
|
||||
|
||||
it('should render correctly', () => {
|
||||
let validateEditor = renderer.create(
|
||||
<ValidateEditor content="foo" onDone={doneFn} isValid={validateFn}/>
|
||||
),
|
||||
tree = validateEditor.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
|
||||
let validateEditor = TestUtils.renderIntoDocument(
|
||||
<ValidateEditor content="foo" onDone={doneFn} isValid={validateFn}/>
|
||||
)
|
||||
it('should handle componentWillReceiveProps', () => {
|
||||
let mockProps = {
|
||||
isValid: s => s.length == 3,
|
||||
content: "bar"
|
||||
}
|
||||
validateEditor.componentWillReceiveProps(mockProps)
|
||||
expect(validateEditor.state.valid).toBeTruthy()
|
||||
validateEditor.componentWillReceiveProps({...mockProps, content: "bars"})
|
||||
expect(validateEditor.state.valid).toBeFalsy()
|
||||
|
||||
})
|
||||
|
||||
it('should handle input', () => {
|
||||
validateEditor.onInput("foo bar")
|
||||
expect(validateFn).toBeCalledWith("foo bar")
|
||||
})
|
||||
|
||||
it('should handle done', () => {
|
||||
// invalid
|
||||
validateEditor.editor.reset = jest.fn()
|
||||
validateEditor.onDone("foo bar")
|
||||
expect(validateEditor.editor.reset).toBeCalled()
|
||||
// valid
|
||||
validateEditor.onDone("bar")
|
||||
expect(doneFn).toBeCalledWith("bar")
|
||||
})
|
||||
})
|
155
web/src/js/__tests__/components/ValueEditor/ValueEditorSpec.js
Normal file
155
web/src/js/__tests__/components/ValueEditor/ValueEditorSpec.js
Normal file
@ -0,0 +1,155 @@
|
||||
import React from 'react'
|
||||
import renderer from 'react-test-renderer'
|
||||
import TestUtils from 'react-dom/test-utils'
|
||||
import ValueEditor from '../../../components/ValueEditor/ValueEditor'
|
||||
import { Key } from '../../../utils'
|
||||
|
||||
describe('ValueEditor Component', () => {
|
||||
|
||||
let mockFn = jest.fn()
|
||||
it ('should render correctly', () => {
|
||||
let valueEditor = renderer.create(
|
||||
<ValueEditor content="foo" onDone={mockFn}/>
|
||||
),
|
||||
tree = valueEditor.toJSON()
|
||||
expect(tree).toMatchSnapshot()
|
||||
})
|
||||
|
||||
let valueEditor = TestUtils.renderIntoDocument(
|
||||
<ValueEditor content="<script>foo</script>" onDone={mockFn}/>
|
||||
)
|
||||
it('should handle this.blur', () => {
|
||||
valueEditor.input.blur = jest.fn()
|
||||
valueEditor.blur()
|
||||
expect(valueEditor.input.blur).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should handle reset', () => {
|
||||
valueEditor.reset()
|
||||
expect(valueEditor.input.innerHTML).toEqual(
|
||||
"<script>foo</script>"
|
||||
)
|
||||
})
|
||||
|
||||
it('should handle paste', () => {
|
||||
let mockEvent = {
|
||||
preventDefault: jest.fn(),
|
||||
clipboardData: { getData: (t) => "foo content"}
|
||||
}
|
||||
document.execCommand = jest.fn()
|
||||
valueEditor.onPaste(mockEvent)
|
||||
expect(document.execCommand).toBeCalledWith('insertHTML', false, "foo content")
|
||||
})
|
||||
|
||||
it('should handle mouseDown', () => {
|
||||
window.addEventListener = jest.fn()
|
||||
valueEditor.onMouseDown({})
|
||||
expect(valueEditor._mouseDown).toBeTruthy()
|
||||
expect(window.addEventListener).toBeCalledWith('mouseup', valueEditor.onMouseUp)
|
||||
})
|
||||
|
||||
it('should handle mouseUp', () => {
|
||||
window.removeEventListener = jest.fn()
|
||||
valueEditor.onMouseUp()
|
||||
expect(window.removeEventListener).toBeCalledWith('mouseup', valueEditor.onMouseUp)
|
||||
})
|
||||
|
||||
it('should handle focus', () => {
|
||||
let mockEvent = { clientX: 1, clientY: 2 },
|
||||
mockSelection = {
|
||||
rangeCount: 1,
|
||||
getRangeAt: jest.fn( (index) => {return { selectNodeContents: jest.fn() }}),
|
||||
removeAllRanges: jest.fn(),
|
||||
addRange: jest.fn()
|
||||
},
|
||||
clearState = (v) => {
|
||||
v._mouseDown = false
|
||||
v._ignore_events = false
|
||||
v.state.editable = false
|
||||
}
|
||||
window.getSelection = () => mockSelection
|
||||
|
||||
// return undefined when mouse down
|
||||
valueEditor.onMouseDown()
|
||||
expect(valueEditor.onFocus(mockEvent)).toEqual(undefined)
|
||||
valueEditor.onMouseUp()
|
||||
|
||||
// sel.rangeCount > 0
|
||||
valueEditor.onFocus(mockEvent)
|
||||
expect(mockSelection.getRangeAt).toBeCalledWith(0)
|
||||
expect(valueEditor.state.editable).toBeTruthy()
|
||||
expect(mockSelection.removeAllRanges).toBeCalled()
|
||||
expect(mockSelection.addRange).toBeCalled()
|
||||
clearState(valueEditor)
|
||||
|
||||
// document.caretPositionFromPoint
|
||||
mockSelection.rangeCount = 0
|
||||
let mockRange = { setStart: jest.fn(), selectNodeContents: jest.fn() }
|
||||
|
||||
document.caretPositionFromPoint = jest.fn((x, y) => {
|
||||
return { offsetNode: 0, offset: x + y}
|
||||
})
|
||||
document.createRange = jest.fn(() => mockRange)
|
||||
valueEditor.onFocus(mockEvent)
|
||||
expect(mockRange.setStart).toBeCalledWith(0, 3)
|
||||
clearState(valueEditor)
|
||||
document.caretPositionFromPoint = null
|
||||
|
||||
//document.caretRangeFromPoint
|
||||
document.caretRangeFromPoint = jest.fn(() => mockRange)
|
||||
valueEditor.onFocus(mockEvent)
|
||||
expect(document.caretRangeFromPoint).toBeCalledWith(1, 2)
|
||||
clearState(valueEditor)
|
||||
document.caretRangeFromPoint = null
|
||||
|
||||
//else
|
||||
valueEditor.onFocus(mockEvent)
|
||||
expect(mockRange.selectNodeContents).toBeCalledWith(valueEditor.input)
|
||||
clearState(valueEditor)
|
||||
})
|
||||
|
||||
it('should handle click', () => {
|
||||
valueEditor.onMouseUp = jest.fn()
|
||||
valueEditor.onFocus = jest.fn()
|
||||
valueEditor.onClick('foo')
|
||||
expect(valueEditor.onMouseUp).toBeCalled()
|
||||
expect(valueEditor.onFocus).toBeCalledWith('foo')
|
||||
})
|
||||
|
||||
it('should handle blur', () => {
|
||||
// return undefined
|
||||
valueEditor._ignore_events = true
|
||||
expect(valueEditor.onBlur({})).toEqual(undefined)
|
||||
// else
|
||||
valueEditor._ignore_events = false
|
||||
valueEditor.onBlur({})
|
||||
expect(valueEditor.state.editable).toBeFalsy()
|
||||
expect(valueEditor.props.onDone).toBeCalledWith(valueEditor.input.textContent)
|
||||
})
|
||||
|
||||
it('should handle key down', () => {
|
||||
let mockKeyEvent = (keyCode, shiftKey=false) => {
|
||||
return {
|
||||
keyCode: keyCode,
|
||||
shiftKey: shiftKey,
|
||||
stopPropagation: jest.fn(),
|
||||
preventDefault: jest.fn()
|
||||
}
|
||||
}
|
||||
valueEditor.reset = jest.fn()
|
||||
valueEditor.blur = jest.fn()
|
||||
valueEditor.onKeyDown(mockKeyEvent(Key.ESC))
|
||||
expect(valueEditor.reset).toBeCalled()
|
||||
expect(valueEditor.blur).toBeCalled()
|
||||
valueEditor.blur.mockReset()
|
||||
|
||||
valueEditor.onKeyDown(mockKeyEvent(Key.ENTER))
|
||||
expect(valueEditor.blur).toBeCalled()
|
||||
|
||||
valueEditor.onKeyDown(mockKeyEvent(Key.SPACE))
|
||||
})
|
||||
|
||||
it('should handle input', () => {
|
||||
valueEditor.onInput()
|
||||
})
|
||||
})
|
@ -0,0 +1,21 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ValidateEditor Component should render correctly 1`] = `
|
||||
<div
|
||||
className="inline-input editable has-success"
|
||||
contentEditable={undefined}
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "foo",
|
||||
}
|
||||
}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onInput={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onPaste={[Function]}
|
||||
tabIndex={0}
|
||||
/>
|
||||
`;
|
@ -0,0 +1,21 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ValueEditor 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}
|
||||
/>
|
||||
`;
|
@ -7,3 +7,30 @@ export function createStore(parts) {
|
||||
applyMiddleware(...[thunk])
|
||||
)
|
||||
}
|
||||
|
||||
export function TFlow(intercepted=false, marked=false, modified=false) {
|
||||
return {
|
||||
intercepted ,
|
||||
marked,
|
||||
modified,
|
||||
id: "foo",
|
||||
request: {
|
||||
scheme: 'http',
|
||||
is_replay: true,
|
||||
method: 'GET',
|
||||
contentLength: 100
|
||||
},
|
||||
response: {
|
||||
status_code: 200,
|
||||
headers: [["Content-Type", 'text/html']],
|
||||
timestamp_end: 200
|
||||
},
|
||||
error: {
|
||||
msg: ''
|
||||
},
|
||||
server_conn: {
|
||||
timestamp_start: 100
|
||||
},
|
||||
type: 'http'
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user