From 4b16e50e5fb39c0c6d7e37e602e340b7f016f9f3 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Tue, 25 Feb 2025 14:54:02 +0100 Subject: [PATCH] ui: export events for e2e --- .../app/components/Session_/Subheader.tsx | 13 ++++ .../Session_/UnitStepsModal/index.tsx | 62 +++++++++++++++++++ .../components/ui/CopyButton/CopyButton.js | 14 ++--- frontend/app/types/session/event.ts | 3 + 4 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 frontend/app/components/Session_/UnitStepsModal/index.tsx diff --git a/frontend/app/components/Session_/Subheader.tsx b/frontend/app/components/Session_/Subheader.tsx index b3efe5863..b1264e954 100644 --- a/frontend/app/components/Session_/Subheader.tsx +++ b/frontend/app/components/Session_/Subheader.tsx @@ -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(, { title: 'Export Events', width: 640 }); + } + return ( <>
Keyboard Shortcuts
, onClick: showKbHelp + }, + { + key: '5', + label:
Export Events
, + onClick: exportEvents, } ] }} diff --git a/frontend/app/components/Session_/UnitStepsModal/index.tsx b/frontend/app/components/Session_/UnitStepsModal/index.tsx new file mode 100644 index 000000000..93a0f96a2 --- /dev/null +++ b/frontend/app/components/Session_/UnitStepsModal/index.tsx @@ -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 ( +
+
+ setActiveFramework(value)} + /> + +
+
+ +
+
+ ); +} + +export default UnitStepsModal; \ No newline at end of file diff --git a/frontend/app/components/ui/CopyButton/CopyButton.js b/frontend/app/components/ui/CopyButton/CopyButton.js index bceb38b31..5df72b999 100644 --- a/frontend/app/components/ui/CopyButton/CopyButton.js +++ b/frontend/app/components/ui/CopyButton/CopyButton.js @@ -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 ( - ) + ); } export default CopyButton diff --git a/frontend/app/types/session/event.ts b/frontend/app/types/session/event.ts index b9b7c1c07..e603b53e5 100644 --- a/frontend/app/types/session/event.ts +++ b/frontend/app/types/session/event.ts @@ -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; }