* ui: change export event ui, add rightblock panel * ui: add timeline select checkbox * ui: keep selected framework in localstorage * ui: on timeline => on the timeline
214 lines
6.3 KiB
TypeScript
214 lines
6.3 KiB
TypeScript
import React from 'react';
|
|
import { TYPES } from 'App/types/session/event';
|
|
import { CodeBlock, Icon } from 'UI';
|
|
import { Select, Radio, Checkbox } from 'antd';
|
|
import { useStore } from 'App/mstore';
|
|
import { observer } from 'mobx-react-lite';
|
|
import { PlayerContext } from 'Components/Session/playerContext';
|
|
import { X } from 'lucide-react';
|
|
import { puppeteerEvents, cypressEvents, playWrightEvents } from './utils';
|
|
|
|
interface Props {
|
|
onClose: () => void;
|
|
}
|
|
|
|
const defaultFrameworkKey = '__$defaultFrameworkKey$__';
|
|
export const getDefaultFramework = () => {
|
|
const stored = localStorage.getItem(defaultFrameworkKey);
|
|
return stored ?? 'cypress';
|
|
}
|
|
export const frameworkIcons = {
|
|
cypress: 'cypress',
|
|
puppeteer: 'puppeteer',
|
|
playwright: 'pwright',
|
|
}
|
|
function UnitStepsModal({ onClose }: Props) {
|
|
const { sessionStore, uiPlayerStore } = useStore();
|
|
const { store, player } = React.useContext(PlayerContext);
|
|
const [eventStr, setEventStr] = React.useState('');
|
|
const [mode, setMode] = React.useState('events');
|
|
const [activeFramework, setActiveFramework] = React.useState(getDefaultFramework);
|
|
const events = React.useMemo(() => {
|
|
if (!uiPlayerStore.exportEventsSelection.enabled) {
|
|
return sessionStore.current.events;
|
|
} else {
|
|
return sessionStore.current.events.filter((ev) => {
|
|
return (
|
|
ev.time >= uiPlayerStore.exportEventsSelection.startTs &&
|
|
ev.time <= uiPlayerStore.exportEventsSelection.endTs
|
|
);
|
|
});
|
|
}
|
|
}, [
|
|
sessionStore.current.events,
|
|
uiPlayerStore.exportEventsSelection.enabled,
|
|
uiPlayerStore.exportEventsSelection.startTs,
|
|
uiPlayerStore.exportEventsSelection.endTs,
|
|
]);
|
|
const { tabNames, currentTab } = store.get();
|
|
|
|
React.useEffect(() => {
|
|
player.pause();
|
|
return () => {
|
|
uiPlayerStore.toggleExportEventsSelection({ enabled: false });
|
|
};
|
|
}, []);
|
|
|
|
React.useEffect(() => {
|
|
const userEventTypes = [TYPES.LOCATION, TYPES.CLICK, TYPES.INPUT];
|
|
|
|
const collections = {
|
|
puppeteer: puppeteerEvents,
|
|
cypress: cypressEvents,
|
|
playwright: playWrightEvents,
|
|
};
|
|
|
|
// @ts-ignore
|
|
const usedCollection = collections[activeFramework];
|
|
|
|
let finalScript = '';
|
|
if (mode === 'test') {
|
|
const pageName = tabNames[currentTab] ?? 'Test Name';
|
|
const firstUrl =
|
|
events.find((ev) => ev.type === TYPES.LOCATION)?.url ?? 'page';
|
|
finalScript += usedCollection.testIntro(pageName, firstUrl);
|
|
finalScript += '\n';
|
|
}
|
|
events.forEach((ev) => {
|
|
if (userEventTypes.includes(ev.type)) {
|
|
if (mode === 'test') {
|
|
finalScript += ' ';
|
|
}
|
|
finalScript += usedCollection[ev.type](ev);
|
|
finalScript += '\n';
|
|
}
|
|
});
|
|
if (mode === 'test') {
|
|
finalScript += usedCollection.testOutro();
|
|
}
|
|
setEventStr(finalScript);
|
|
}, [events, activeFramework, mode]);
|
|
|
|
const enableZoom = () => {
|
|
const time = store.get().time;
|
|
const endTime = store.get().endTime;
|
|
const closestEvent = sessionStore.current.events.reduce((prev, curr) => {
|
|
return Math.abs(curr.time - time) < Math.abs(prev.time - time)
|
|
? curr
|
|
: prev;
|
|
});
|
|
const closestInd = sessionStore.current.events.indexOf(closestEvent);
|
|
if (closestEvent) {
|
|
const beforeCenter = closestInd > 4 ? closestInd - 4 : null;
|
|
const afterCenter =
|
|
closestInd < sessionStore.current.events.length - 4
|
|
? closestInd + 4
|
|
: null;
|
|
|
|
uiPlayerStore.toggleExportEventsSelection({
|
|
enabled: true,
|
|
range: [
|
|
beforeCenter ? sessionStore.current.events[beforeCenter].time : 0,
|
|
afterCenter ? sessionStore.current.events[afterCenter].time : endTime,
|
|
],
|
|
});
|
|
} else {
|
|
const distance = Math.max(endTime / 40, 2500);
|
|
|
|
uiPlayerStore.toggleExportEventsSelection({
|
|
enabled: true,
|
|
range: [
|
|
Math.max(time - distance, 0),
|
|
Math.min(time + distance, endTime),
|
|
],
|
|
});
|
|
}
|
|
};
|
|
|
|
const toggleZoom = (enabled?: boolean) => {
|
|
if (enabled) {
|
|
enableZoom();
|
|
} else {
|
|
uiPlayerStore.toggleExportEventsSelection({ enabled: false });
|
|
}
|
|
};
|
|
|
|
const changeFramework = (framework: string) => {
|
|
localStorage.setItem(defaultFrameworkKey, framework);
|
|
setActiveFramework(framework);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className={'bg-white h-screen w-full flex flex-col items-start gap-2 p-4'}
|
|
style={{ marginTop: -50 }}
|
|
>
|
|
<div className={'flex items-center justify-between w-full'}>
|
|
<div className={'font-semibold text-xl'}>Copy Events</div>
|
|
<div className={'cursor-pointer'} onClick={onClose}>
|
|
<X size={18} />
|
|
</div>
|
|
</div>
|
|
<Select
|
|
className={'w-full'}
|
|
options={[
|
|
{
|
|
label: (
|
|
<div className={'flex items-center gap-2'}>
|
|
<Icon name={'cypress'} size={18} />
|
|
<div>Cypress</div>
|
|
</div>
|
|
),
|
|
value: 'cypress',
|
|
},
|
|
{
|
|
label: (
|
|
<div className={'flex items-center gap-2'}>
|
|
<Icon name={'puppeteer'} size={18} />
|
|
<div>Puppeteer</div>
|
|
</div>
|
|
),
|
|
value: 'puppeteer',
|
|
},
|
|
{
|
|
label: (
|
|
<div className={'flex items-center gap-2'}>
|
|
<Icon name={'pwright'} size={18} />
|
|
<div>Playwright</div>
|
|
</div>
|
|
),
|
|
value: 'playwright',
|
|
},
|
|
]}
|
|
value={activeFramework}
|
|
onChange={changeFramework}
|
|
/>
|
|
<Radio.Group
|
|
value={mode}
|
|
onChange={(e) => setMode(e.target.value)}
|
|
className={'w-full'}
|
|
>
|
|
<Radio value={'events'}>Events Only</Radio>
|
|
<Radio value={'test'}>Complete Test</Radio>
|
|
</Radio.Group>
|
|
<Checkbox
|
|
value={uiPlayerStore.exportEventsSelection.enabled}
|
|
onChange={(e) => toggleZoom(e.target.checked)}
|
|
>
|
|
Select events on the timeline
|
|
</Checkbox>
|
|
<div className={'w-full'}>
|
|
<CodeBlock
|
|
width={340}
|
|
height={'calc(100vh - 146px)'}
|
|
extra={`${events.length} Events`}
|
|
copy
|
|
code={eventStr}
|
|
language={'javascript'}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default observer(UnitStepsModal);
|