diff --git a/.eslintrc.js b/.eslintrc.js index 667c0fc1..ef57a1b1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -38,6 +38,7 @@ module.exports = { }, }, rules: { + '@typescript-eslint/no-empty-function': 'off', ...importRules, }, } diff --git a/src/icons/clear.svg b/src/icons/clear.svg index 5f1267d7..84aaef85 100644 --- a/src/icons/clear.svg +++ b/src/icons/clear.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/src/icons/index.ts b/src/icons/index.ts index 7ce53b99..75e4c55c 100644 --- a/src/icons/index.ts +++ b/src/icons/index.ts @@ -1,2 +1,3 @@ export { default as Plus } from './plus.svg' export { default as Clear } from './clear.svg' +export { default as LevelCrossing } from './level-crossing.svg' diff --git a/src/icons/level-crossing.svg b/src/icons/level-crossing.svg new file mode 100644 index 00000000..6cc7c4a1 --- /dev/null +++ b/src/icons/level-crossing.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/src/icons/plus.svg b/src/icons/plus.svg index 93b8cea7..6a7811e8 100644 --- a/src/icons/plus.svg +++ b/src/icons/plus.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/src/intercept/__tests__/debugger.ts b/src/interceptor/__tests__/debugger.ts similarity index 100% rename from src/intercept/__tests__/debugger.ts rename to src/interceptor/__tests__/debugger.ts diff --git a/src/intercept/__tests__/index.ts b/src/interceptor/__tests__/index.ts similarity index 98% rename from src/intercept/__tests__/index.ts rename to src/interceptor/__tests__/index.ts index 96228df4..88a9faf0 100644 --- a/src/intercept/__tests__/index.ts +++ b/src/interceptor/__tests__/index.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ import { chrome } from 'jest-chrome' import { RequestPausedEvent, listen, subscribe, unlisten } from '../debugger' diff --git a/src/intercept/__tests__/intercept.ts b/src/interceptor/__tests__/intercept.ts similarity index 100% rename from src/intercept/__tests__/intercept.ts rename to src/interceptor/__tests__/intercept.ts diff --git a/src/intercept/debugger.ts b/src/interceptor/debugger.ts similarity index 100% rename from src/intercept/debugger.ts rename to src/interceptor/debugger.ts diff --git a/src/intercept/index.ts b/src/interceptor/index.ts similarity index 100% rename from src/intercept/index.ts rename to src/interceptor/index.ts diff --git a/src/intercept/intercept.ts b/src/interceptor/intercept.ts similarity index 100% rename from src/intercept/intercept.ts rename to src/interceptor/intercept.ts diff --git a/src/interceptor/react/index.ts b/src/interceptor/react/index.ts new file mode 100644 index 00000000..4d69a160 --- /dev/null +++ b/src/interceptor/react/index.ts @@ -0,0 +1 @@ +export { Provider as InterceptProvider, useIntercepts } from './intercept' diff --git a/src/interceptor/react/intercept.tsx b/src/interceptor/react/intercept.tsx new file mode 100644 index 00000000..e63d242b --- /dev/null +++ b/src/interceptor/react/intercept.tsx @@ -0,0 +1,43 @@ +import * as React from 'react' +import { createContext, useContext, useState } from 'react' + +import * as intercept from '../intercept' + +interface InterceptContextType { + intercepts: intercept.Intercept[] + addIntercept: (pattern: string) => void + removeIntercept: (inter: intercept.Intercept) => void +} + +const InterceptContext = createContext({ + intercepts: [], + addIntercept: () => {}, + removeIntercept: () => {}, +}) + +interface Props { + children: React.ReactNode +} + +export const Provider = ({ children }: Props) => { + const [intercepts, setIntercepts] = useState([...intercept.intercepts]) + + const addIntercept = (pattern: string) => { + intercept.addIntercept({ pattern, enabled: true }) + setIntercepts([...intercept.intercepts]) + } + const removeIntercept = (inter: intercept.Intercept) => { + intercept.removeIntercept(inter) + setIntercepts([...intercept.intercepts]) + } + + return ( + + {children} + + ) +} + +export const useIntercepts = () => useContext(InterceptContext) diff --git a/src/intercept/request.ts b/src/interceptor/request.ts similarity index 100% rename from src/intercept/request.ts rename to src/interceptor/request.ts diff --git a/src/panel/App.tsx b/src/panel/App.tsx index d6f25e89..a1da1949 100644 --- a/src/panel/App.tsx +++ b/src/panel/App.tsx @@ -1,14 +1,15 @@ import * as React from 'react' import { useLayoutEffect, useReducer } from 'react' -import * as Intercept from '@/intercept' +import * as Interceptor from '@/interceptor' +import { InterceptProvider } from '@/interceptor/react' import Main from './Main' import Sidebar from './Sidebar' const App = () => { const [requests, pushRequest] = useReducer( - (requests: Intercept.Request[], req: Intercept.Request) => [ + (requests: Interceptor.Request[], req: Interceptor.Request) => [ ...requests, req, ], @@ -16,25 +17,27 @@ const App = () => { ) useLayoutEffect(() => { - Intercept.listen() - const unsubscribe = Intercept.subscribe((req) => { + Interceptor.listen() + const unsubscribe = Interceptor.subscribe((req) => { pushRequest(req) }) return () => { unsubscribe() - Intercept.unlisten() + Interceptor.unlisten() } }, []) return ( -
- -
-
+ +
+ +
+
+
) } diff --git a/src/panel/InterceptList.tsx b/src/panel/InterceptList.tsx index f5e690bc..8433fed0 100644 --- a/src/panel/InterceptList.tsx +++ b/src/panel/InterceptList.tsx @@ -2,13 +2,14 @@ import * as React from 'react' import { useMemo, useState } from 'react' import { Clear as ClearIcon, Plus as PlusIcon } from '@/icons' -import * as intercept from '@/intercept' +import * as Interceptor from '@/interceptor' +import { useIntercepts } from '@/interceptor/react' import List from './components/List' interface ItemProps { - inter: intercept.Intercept - onDelete: (inter: intercept.Intercept) => void + inter: Interceptor.Intercept + onDelete: (inter: Interceptor.Intercept) => void } const Item = ({ inter, onDelete }: ItemProps) => { @@ -41,15 +42,7 @@ interface Props { } const InterceptList = ({ className }: Props) => { - const [intercepts, setIntercepts] = useState([...intercept.intercepts]) - const addIntercept = (pattern: string) => { - intercept.addIntercept({ pattern, enabled: true }) - setIntercepts([...intercept.intercepts]) - } - const removeIntercept = (inter: intercept.Intercept) => { - intercept.removeIntercept(inter) - setIntercepts([...intercept.intercepts]) - } + const { intercepts, addIntercept, removeIntercept } = useIntercepts() const items = useMemo( () => diff --git a/src/panel/Main.tsx b/src/panel/Main.tsx index 362e3cbf..4bebb09d 100644 --- a/src/panel/Main.tsx +++ b/src/panel/Main.tsx @@ -1,12 +1,14 @@ import * as React from 'react' +import Welcome from './Welcome' + interface Props { className?: string } const Main = ({ className }: Props) => ( -
- Hello World! +
+
) diff --git a/src/panel/RequestList.tsx b/src/panel/RequestList.tsx index 4cca2ab8..d3cab26d 100644 --- a/src/panel/RequestList.tsx +++ b/src/panel/RequestList.tsx @@ -1,12 +1,12 @@ import * as React from 'react' import { useMemo } from 'react' -import * as Intercept from '@/intercept' +import * as Interceptor from '@/interceptor' import List from './components/List' interface ItemProps { - request: Intercept.Request + request: Interceptor.Request } const Item = ({ request }: ItemProps) => ( @@ -17,7 +17,7 @@ const Item = ({ request }: ItemProps) => ( interface Props { className?: string - requests: Intercept.Request[] + requests: Interceptor.Request[] } const RequestList = ({ className, requests }: Props) => { diff --git a/src/panel/Sidebar.tsx b/src/panel/Sidebar.tsx index 80daf133..cf6f79a4 100644 --- a/src/panel/Sidebar.tsx +++ b/src/panel/Sidebar.tsx @@ -1,21 +1,22 @@ import * as React from 'react' -import * as Intercept from '@/intercept' +import * as Interceptor from '@/interceptor' import InterceptList from './InterceptList' import RequestList from './RequestList' interface Props { className?: string - requests: Intercept.Request[] + requests: Interceptor.Request[] } -const Sidebar = ({ className, requests }: Props) => ( +const Sidebar = ({ className = '', requests }: Props) => ( ) diff --git a/src/panel/Welcome.tsx b/src/panel/Welcome.tsx new file mode 100644 index 00000000..3c20be58 --- /dev/null +++ b/src/panel/Welcome.tsx @@ -0,0 +1,33 @@ +import * as React from 'react' + +import { LevelCrossing } from '@/icons' +import { useIntercepts } from '@/interceptor/react' + +interface Props { + className?: string +} + +const Welcome = ({ className = '' }: Props) => { + const { addIntercept } = useIntercepts() + + return ( +
+
+ +
+
Welcome to Interceptor
+ +
+ ) +} + +export default Welcome diff --git a/src/panel/__tests__/App.tsx b/src/panel/__tests__/App.tsx index c2607445..a70c88db 100644 --- a/src/panel/__tests__/App.tsx +++ b/src/panel/__tests__/App.tsx @@ -3,12 +3,12 @@ import { cleanup, render, waitFor } from '@testing-library/react' import * as React from 'react' import '@testing-library/jest-dom' -import * as Intercept from '@/intercept' +import * as Interceptor from '@/interceptor' import App from '../App' -jest.mock('@/intercept') -const mockedIntercept = Intercept as jest.Mocked +jest.mock('@/interceptor') +const mockedIntercept = Interceptor as jest.Mocked describe('[App]', () => { const unsubscribe = jest.fn() @@ -38,7 +38,7 @@ describe('[App]', () => { }) it('should update after callback', async () => { - let listener: Intercept.RequestEventListener = () => { + let listener: Interceptor.RequestEventListener = () => { throw new Error('listener called before subscribe') } mockedIntercept.subscribe.mockImplementation((l) => { @@ -53,7 +53,7 @@ describe('[App]', () => { const req = { method: 'GET', url: 'https://example.com', - } as Intercept.Request + } as Interceptor.Request await waitFor(() => listener(req)) expect(container).not.toEqual(snapshot) diff --git a/src/panel/__tests__/InterceptList.tsx b/src/panel/__tests__/InterceptList.tsx index bd463fe6..a10cb518 100644 --- a/src/panel/__tests__/InterceptList.tsx +++ b/src/panel/__tests__/InterceptList.tsx @@ -3,6 +3,8 @@ import { cleanup, fireEvent, render } from '@testing-library/react' import * as React from 'react' import '@testing-library/jest-dom' +import { InterceptProvider } from '@/interceptor/react' + import InterceptList from '../InterceptList' describe('[InterceptList]', () => { @@ -17,7 +19,11 @@ describe('[InterceptList]', () => { }) it('should match snapshots after clicking buttons', () => { - const { container, getByRole } = render() + const { container, getByRole } = render( + + + + ) const addButton = getByRole('button', { name: 'Add intercept' }) fireEvent.click(addButton) diff --git a/src/panel/__tests__/RequestList.tsx b/src/panel/__tests__/RequestList.tsx index bf34fed2..9897e44c 100644 --- a/src/panel/__tests__/RequestList.tsx +++ b/src/panel/__tests__/RequestList.tsx @@ -3,12 +3,12 @@ import { cleanup, render } from '@testing-library/react' import * as React from 'react' import '@testing-library/jest-dom' -import * as Intercept from '@/intercept' +import * as Interceptor from '@/interceptor' import RequestList from '../RequestList' // mock request -const request: Intercept.Request = { +const request: Interceptor.Request = { headers: {}, initialPriority: 'Medium', method: 'GET', diff --git a/src/panel/__tests__/Sidebar.tsx b/src/panel/__tests__/Sidebar.tsx index 75baabac..32a83afd 100644 --- a/src/panel/__tests__/Sidebar.tsx +++ b/src/panel/__tests__/Sidebar.tsx @@ -3,12 +3,12 @@ import { cleanup, render } from '@testing-library/react' import * as React from 'react' import '@testing-library/jest-dom' -import * as Intercept from '@/intercept' +import * as Interceptor from '@/interceptor' import Sidebar from '../Sidebar' // mock request -const request: Intercept.Request = { +const request: Interceptor.Request = { headers: {}, initialPriority: 'Medium', method: 'GET', diff --git a/src/panel/__tests__/Welcome.tsx b/src/panel/__tests__/Welcome.tsx new file mode 100644 index 00000000..f6a4acbd --- /dev/null +++ b/src/panel/__tests__/Welcome.tsx @@ -0,0 +1,25 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { cleanup, fireEvent, render } from '@testing-library/react' +import * as React from 'react' +import '@testing-library/jest-dom' + +import Welcome from '../Welcome' + +describe('[Welcome]', () => { + afterEach(() => { + cleanup() + }) + + it('should match empty snapshot', () => { + const { container } = render() + expect(container).toMatchSnapshot() + }) + + it('should click button', () => { + const { container, getByRole } = render() + const button = getByRole('button', { name: 'Add intercept' }) + fireEvent.click(button) + + expect(container).toMatchSnapshot() + }) +}) diff --git a/src/panel/__tests__/__snapshots__/App.tsx.snap b/src/panel/__tests__/__snapshots__/App.tsx.snap index 18e63b8a..584e1dd6 100644 --- a/src/panel/__tests__/__snapshots__/App.tsx.snap +++ b/src/panel/__tests__/__snapshots__/App.tsx.snap @@ -50,10 +50,32 @@ exports[`[App] matches snapshot 1`] = `
- Hello World! +
+
+ +
+
+ Welcome to Interceptor +
+ +
@@ -117,10 +139,32 @@ exports[`[App] should update after callback 1`] = `
- Hello World! +
+
+ +
+
+ Welcome to Interceptor +
+ +
diff --git a/src/panel/__tests__/__snapshots__/InterceptList.tsx.snap b/src/panel/__tests__/__snapshots__/InterceptList.tsx.snap index dbfbffcc..5afcf5fc 100644 --- a/src/panel/__tests__/__snapshots__/InterceptList.tsx.snap +++ b/src/panel/__tests__/__snapshots__/InterceptList.tsx.snap @@ -3,7 +3,7 @@ exports[`[InterceptList] should match empty snapshot 1`] = `
- Hello World! +
+
+ +
+
+ Welcome to Interceptor +
+ +
`; diff --git a/src/panel/__tests__/__snapshots__/RequestList.tsx.snap b/src/panel/__tests__/__snapshots__/RequestList.tsx.snap index 6343ed26..c8053800 100644 --- a/src/panel/__tests__/__snapshots__/RequestList.tsx.snap +++ b/src/panel/__tests__/__snapshots__/RequestList.tsx.snap @@ -3,7 +3,7 @@ exports[`[RequestList] should match empty snapshot 1`] = `