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;
}