experiment: special tracing view for API testing

This commit is contained in:
Simon Knott 2024-09-18 17:11:43 +02:00
parent ddd43d0f20
commit 5309959e4f
No known key found for this signature in database
GPG key ID: 8CEDC00028084AEC
4 changed files with 29 additions and 18 deletions

View file

@ -0,0 +1,8 @@
import { test, expect } from '@playwright/test';
test('should get post #1', async ({ request }) => {
const post = await request.get(`https://jsonplaceholder.typicode.com/posts/1`);
expect(post.ok()).toBeTruthy();
await request.post(`https://jsonplaceholder.typicode.com/posts/1`);
});

View file

@ -24,29 +24,29 @@ import { generateCurlCommand, generateFetchCall } from '../third_party/devtools'
import { CopyToClipboard } from './copyToClipboard'; import { CopyToClipboard } from './copyToClipboard';
export const NetworkResourceDetails: React.FunctionComponent<{ export const NetworkResourceDetails: React.FunctionComponent<{
resource: ResourceSnapshot; resource?: ResourceSnapshot;
onClose: () => void; onClose?: () => void;
}> = ({ resource, onClose }) => { }> = ({ resource, onClose }) => {
const [selectedTab, setSelectedTab] = React.useState('request'); const [selectedTab, setSelectedTab] = React.useState('request');
return <TabbedPane return <TabbedPane
dataTestId='network-request-details' dataTestId='network-request-details'
leftToolbar={[<ToolbarButton key='close' icon='close' title='Close' onClick={onClose}></ToolbarButton>]} leftToolbar={onClose ? [<ToolbarButton key='close' icon='close' title='Close' onClick={onClose}></ToolbarButton>] : undefined}
tabs={[ tabs={[
{ {
id: 'request', id: 'request',
title: 'Request', title: 'Request',
render: () => <RequestTab resource={resource}/>, render: () => resource ? <RequestTab resource={resource}/> : <div/>,
}, },
{ {
id: 'response', id: 'response',
title: 'Response', title: 'Response',
render: () => <ResponseTab resource={resource}/>, render: () => resource ? <ResponseTab resource={resource}/> : <div/>,
}, },
{ {
id: 'body', id: 'body',
title: 'Body', title: 'Body',
render: () => <BodyTab resource={resource}/>, render: () => resource ? <BodyTab resource={resource}/> : <div/>,
}, },
]} ]}
selectedTab={selectedTab} selectedTab={selectedTab}

View file

@ -108,6 +108,7 @@ export const UIModeView: React.FC<{}> = ({
const [showRouteActions, setShowRouteActions] = useSetting('show-route-actions', true); const [showRouteActions, setShowRouteActions] = useSetting('show-route-actions', true);
const [darkMode, setDarkMode] = useDarkModeSetting(); const [darkMode, setDarkMode] = useDarkModeSetting();
const [showScreenshot, setShowScreenshot] = useSetting('screenshot-instead-of-snapshot', false); const [showScreenshot, setShowScreenshot] = useSetting('screenshot-instead-of-snapshot', false);
const [apiTestingView, setApiTestingView] = useSetting('api-testing-view', false);
const inputRef = React.useRef<HTMLInputElement>(null); const inputRef = React.useRef<HTMLInputElement>(null);
@ -528,6 +529,7 @@ export const UIModeView: React.FC<{}> = ({
{ value: darkMode, set: setDarkMode, title: 'Dark mode' }, { value: darkMode, set: setDarkMode, title: 'Dark mode' },
{ value: showRouteActions, set: setShowRouteActions, title: 'Show route actions' }, { value: showRouteActions, set: setShowRouteActions, title: 'Show route actions' },
{ value: showScreenshot, set: setShowScreenshot, title: 'Show screenshot instead of snapshot' }, { value: showScreenshot, set: setShowScreenshot, title: 'Show screenshot instead of snapshot' },
{ value: apiTestingView, set: setApiTestingView, title: 'API Testing view' },
]} />} ]} />}
</div> </div>
} }

View file

@ -43,6 +43,7 @@ import './workbench.css';
import { testStatusIcon, testStatusText } from './testUtils'; import { testStatusIcon, testStatusText } from './testUtils';
import type { UITestStatus } from './testUtils'; import type { UITestStatus } from './testUtils';
import { SettingsView } from './settingsView'; import { SettingsView } from './settingsView';
import { NetworkResourceDetails } from './networkResourceDetails';
export const Workbench: React.FunctionComponent<{ export const Workbench: React.FunctionComponent<{
model?: modelUtil.MultiTraceModel, model?: modelUtil.MultiTraceModel,
@ -72,6 +73,7 @@ export const Workbench: React.FunctionComponent<{
const [sidebarLocation, setSidebarLocation] = useSetting<'bottom' | 'right'>('propertiesSidebarLocation', 'bottom'); const [sidebarLocation, setSidebarLocation] = useSetting<'bottom' | 'right'>('propertiesSidebarLocation', 'bottom');
const [showRouteActions, setShowRouteActions] = useSetting('show-route-actions', true); const [showRouteActions, setShowRouteActions] = useSetting('show-route-actions', true);
const [showScreenshot, setShowScreenshot] = useSetting('screenshot-instead-of-snapshot', false); const [showScreenshot, setShowScreenshot] = useSetting('screenshot-instead-of-snapshot', false);
const [apiTestingView, setApiTestingView] = useSetting('api-testing-view', false);
const filteredActions = React.useMemo(() => { const filteredActions = React.useMemo(() => {
return (model?.actions || []).filter(action => showRouteActions || !isRouteAction(action)); return (model?.actions || []).filter(action => showRouteActions || !isRouteAction(action));
@ -235,16 +237,10 @@ export const Workbench: React.FunctionComponent<{
render: () => <AttachmentsTab model={model} /> render: () => <AttachmentsTab model={model} />
}; };
const tabs: TabbedPaneTabModel[] = [ const tabs: TabbedPaneTabModel[] =
inspectorTab, apiTestingView
callTab, ? [callTab, logTab, errorsTab, networkTab, attachmentsTab]
logTab, : [inspectorTab, callTab, logTab, errorsTab, consoleTab, networkTab, sourceTab, attachmentsTab];
errorsTab,
consoleTab,
networkTab,
sourceTab,
attachmentsTab,
];
if (annotations !== undefined) { if (annotations !== undefined) {
const annotationsTab: TabbedPaneTabModel = { const annotationsTab: TabbedPaneTabModel = {
@ -312,10 +308,15 @@ export const Workbench: React.FunctionComponent<{
title: 'Settings', title: 'Settings',
component: <SettingsView settings={[ component: <SettingsView settings={[
{ value: showRouteActions, set: setShowRouteActions, title: 'Show route actions' }, { value: showRouteActions, set: setShowRouteActions, title: 'Show route actions' },
{ value: showScreenshot, set: setShowScreenshot, title: 'Show screenshot instead of snapshot' } { value: showScreenshot, set: setShowScreenshot, title: 'Show screenshot instead of snapshot' },
{ value: apiTestingView, set: setApiTestingView, title: 'API Testing View' }
]}/>, ]}/>,
}; };
let entryForSelectedAction: Entry | undefined;
if (selectedAction?.method === 'fetch')
entryForSelectedAction = networkModel.resources.find(resource => resource.request.url === selectedAction.params.url && resource.request.method === selectedAction.params.method);
return <div className='vbox workbench' {...(inert ? { inert: 'true' } : {})}> return <div className='vbox workbench' {...(inert ? { inert: 'true' } : {})}>
<Timeline <Timeline
model={model} model={model}
@ -337,7 +338,7 @@ export const Workbench: React.FunctionComponent<{
orientation='horizontal' orientation='horizontal'
sidebarIsFirst sidebarIsFirst
settingName='actionListSidebar' settingName='actionListSidebar'
main={<SnapshotTab main={apiTestingView ? <NetworkResourceDetails resource={entryForSelectedAction} /> : <SnapshotTab
action={activeAction} action={activeAction}
model={model} model={model}
sdkLanguage={sdkLanguage} sdkLanguage={sdkLanguage}