ui: export events for e2e

This commit is contained in:
nick-delirium 2025-02-25 14:54:02 +01:00
parent 735b86d778
commit 4b16e50e5f
No known key found for this signature in database
GPG key ID: 93ABD695DF5FDBA0
4 changed files with 85 additions and 7 deletions

View file

@ -21,6 +21,7 @@ import { Bookmark as BookmarkIcn, BookmarkCheck, Vault } from 'lucide-react';
import { useModal } from 'Components/ModalContext';
import IssueForm from 'Components/Session_/Issues/IssueForm';
import ShareModal from '../shared/SharePopup/SharePopup';
import UnitStepsModal from "./UnitStepsModal";
const disableDevtools = 'or_devtools_uxt_toggle';
@ -116,6 +117,13 @@ function SubHeader(props) {
});
};
const exportEvents = () => {
const allEvents = sessionStore.current.events;
const width = store.get().width;
const height = store.get().height;
openModal(<UnitStepsModal width={width} height={height} events={allEvents} />, { title: 'Export Events', width: 640 });
}
return (
<>
<div
@ -187,6 +195,11 @@ function SubHeader(props) {
<span>Keyboard Shortcuts</span>
</div>,
onClick: showKbHelp
},
{
key: '5',
label: <div className={'flex items-center gap-2'}>Export Events</div>,
onClick: exportEvents,
}
]
}}

View file

@ -0,0 +1,62 @@
import React from "react";
import { TYPES, Input, Click, Location } from 'App/types/session/event'
import { CodeBlock, CopyButton } from "UI";
import { Segmented } from 'antd';
interface Props {
events: Input[] | Click[] | Location[];
width: number;
height: number;
}
function UnitStepsModal({ events, width, height }: Props) {
const [eventStr, setEventStr] = React.useState('')
const [activeFramework, setActiveFramework] = React.useState('puppeteer')
React.useEffect(() => {
const userEventTypes = [TYPES.LOCATION, TYPES.CLICK, TYPES.INPUT]
const puppeteerEvents = {
[TYPES.LOCATION]: (event: Location) => `await page.goto('${event.url}')`,
[TYPES.CLICK]: (event: Click) => `await page.locator('${event.selector.length ? event.selector : event.label}').click()`,
[TYPES.INPUT]: (event: Input) => `await page.locator('${event.label}').type('Test Input')`,
'screen': () => `await page.setViewport({width: ${width}, height: ${height})`
}
const cypressEvents = {
[TYPES.LOCATION]: (event: Location) => `cy.visit('${event.url}')`,
[TYPES.CLICK]: (event: Click) => `cy.get('${event.selector.length ? event.selector : event.label}').click()`,
[TYPES.INPUT]: (event: Input) => `cy.get('${event.label}').type('Test Input')`,
'screen': () => `cy.viewport(${width}, ${height})`
}
const usedCollection = activeFramework === 'puppeteer' ? puppeteerEvents : cypressEvents
let finalScript = ''
events.forEach((ev) => {
if (userEventTypes.includes(ev.type)) {
finalScript += usedCollection[ev.type](ev)
finalScript += '\n'
}
})
setEventStr(finalScript)
}, [events, activeFramework])
return (
<div className={'bg-white h-full flex flex-col items-start gap-2'}>
<div className={'flex items-center gap-4'}>
<Segmented
options={[
{ label: 'Puppeteer', value: 'puppeteer' },
{ label: 'Cypress', value: 'cypress' }
]}
value={activeFramework}
onChange={(value) => setActiveFramework(value)}
/>
<CopyButton size={'middle'} variant={'default'} content={eventStr} className={'capitalize font-medium text-neutral-400'} />
</div>
<div className={'w-full'}>
<CodeBlock code={eventStr} language={'javascript'} />
</div>
</div>
);
}
export default UnitStepsModal;

View file

@ -3,7 +3,7 @@ import { useState } from 'react';
import copy from 'copy-to-clipboard';
import { Button } from 'antd';
function CopyButton({ content, variant="text-primary", className = '', btnText = 'copy' }) {
function CopyButton({ content, variant="text", className = 'capitalize mt-2 font-medium text-neutral-400', btnText = 'copy', size = "small" }) {
const [copied, setCopied] = useState(false)
const copyHandler = () => {
@ -16,14 +16,14 @@ function CopyButton({ content, variant="text-primary", className = '', btnText
return (
<Button
type='text'
onClick={ copyHandler }
size='small'
className='capitalize mt-2 font-medium text-neutral-400'
type={variant}
onClick={copyHandler}
size={size}
className={className}
>
{ copied ? 'copied' : btnText }
{copied ? 'copied' : btnText}
</Button>
)
);
}
export default CopyButton

View file

@ -49,6 +49,7 @@ interface ClickEvent extends IEvent {
targetContent: string;
count: number;
hesitation: number;
selector: string;
}
interface TouchEvent extends IEvent {
@ -141,12 +142,14 @@ export class Click extends Event {
targetContent = '';
count: number;
hesitation: number = 0;
selector: string;
constructor(evt: ClickEvent, isClickRage?: boolean) {
super(evt);
this.targetContent = evt.targetContent;
this.count = evt.count;
this.hesitation = evt.hesitation;
this.selector = evt.selector;
if (isClickRage) {
this.type = CLICKRAGE;
}