appium-session-recorder 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -16
- package/dist/index.js +32422 -0
- package/dist/ui/assets/index-CUcJNRfB.css +1 -0
- package/dist/ui/assets/index-Cl_X3tPj.js +4 -0
- package/{src → dist}/ui/index.html +2 -1
- package/package.json +10 -3
- package/bun.lock +0 -731
- package/src/cli/arg-parser.ts +0 -311
- package/src/cli/commands/drive.ts +0 -147
- package/src/cli/commands/index.ts +0 -54
- package/src/cli/commands/proxy.ts +0 -41
- package/src/cli/commands/screen.ts +0 -73
- package/src/cli/commands/selectors.ts +0 -42
- package/src/cli/commands/session.ts +0 -64
- package/src/cli/commands/types.ts +0 -11
- package/src/cli/index.ts +0 -158
- package/src/cli/prompts.ts +0 -64
- package/src/cli/response.ts +0 -44
- package/src/core/appium/client.ts +0 -248
- package/src/core/index.ts +0 -5
- package/src/core/selectors/generate-candidates.ts +0 -155
- package/src/core/selectors/score-candidates.ts +0 -184
- package/src/core/types.ts +0 -79
- package/src/core/xml/parse-source.ts +0 -197
- package/src/index.ts +0 -7
- package/src/server/appium-client.ts +0 -24
- package/src/server/index.ts +0 -6
- package/src/server/interaction-recorder.ts +0 -74
- package/src/server/proxy-middleware.ts +0 -68
- package/src/server/routes.ts +0 -53
- package/src/server/server.ts +0 -43
- package/src/server/types.ts +0 -34
- package/src/ui/bun.lock +0 -311
- package/src/ui/package.json +0 -20
- package/src/ui/src/App.css +0 -12
- package/src/ui/src/App.tsx +0 -41
- package/src/ui/src/components/ActionCarousel.css +0 -128
- package/src/ui/src/components/ActionCarousel.tsx +0 -92
- package/src/ui/src/components/Inspector.css +0 -314
- package/src/ui/src/components/Inspector.tsx +0 -265
- package/src/ui/src/components/InteractionCard.css +0 -159
- package/src/ui/src/components/InteractionCard.tsx +0 -60
- package/src/ui/src/components/MainInspector.css +0 -304
- package/src/ui/src/components/MainInspector.tsx +0 -304
- package/src/ui/src/components/Stats.css +0 -27
- package/src/ui/src/components/Timeline.css +0 -31
- package/src/ui/src/components/Timeline.tsx +0 -37
- package/src/ui/src/hooks/useInteractions.ts +0 -73
- package/src/ui/src/index.tsx +0 -11
- package/src/ui/src/services/api.ts +0 -41
- package/src/ui/src/styles/tokens.css +0 -126
- package/src/ui/src/types.ts +0 -34
- package/src/ui/src/utils/__tests__/locators.test.ts +0 -304
- package/src/ui/src/utils/__tests__/xml-parser.test.ts +0 -326
- package/src/ui/src/utils/locators.ts +0 -14
- package/src/ui/src/utils/xml-parser.ts +0 -45
- package/src/ui/tsconfig.json +0 -34
- package/src/ui/tsconfig.node.json +0 -11
- package/src/ui/vite.config.ts +0 -22
- package/tests/cli/arg-parser.test.ts +0 -397
- package/tests/cli/drive-commands.test.ts +0 -151
- package/tests/cli/selectors-best.test.ts +0 -42
- package/tests/cli/session-commands.test.ts +0 -53
- package/tests/core/selector-candidates.test.ts +0 -83
- package/tests/core/selector-scoring.test.ts +0 -75
- package/tests/core/xml-parser.test.ts +0 -56
- package/tests/server/appium-client.test.ts +0 -229
- package/tests/server/interaction-recorder.test.ts +0 -377
- package/tests/server/proxy-middleware.test.ts +0 -343
- package/tests/server/routes.test.ts +0 -305
- package/tsconfig.json +0 -26
- package/vitest.config.ts +0 -16
- package/vitest.ui.config.ts +0 -15
- package/workflow.gif +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.carousel{display:flex;align-items:center;gap:var(--spacing-4);padding:var(--spacing-3) var(--spacing-6);background:var(--color-bg-secondary);border-bottom:1px solid var(--color-border)}.carousel-empty{flex:1;display:flex;align-items:center;justify-content:center;gap:var(--spacing-3);color:var(--color-text-tertiary);font-size:var(--font-size-sm);padding:var(--spacing-2) 0}.carousel-empty-icon{font-size:var(--font-size-lg)}.carousel-btn{background:var(--color-bg-secondary);color:var(--color-text-secondary);border:1px solid var(--color-border);padding:var(--spacing-2) var(--spacing-4);border-radius:var(--radius-lg);cursor:pointer;font-weight:var(--font-weight-medium);font-size:var(--font-size-sm);transition:all var(--transition-fast);white-space:nowrap}.carousel-btn:hover:not(:disabled){background:var(--color-accent-primary);color:#fff;border-color:var(--color-accent-primary)}.carousel-btn:disabled{opacity:.35;cursor:not-allowed}.carousel-info{flex:1;display:flex;flex-direction:column;align-items:center;gap:var(--spacing-1)}.carousel-counter{font-size:var(--font-size-xs);color:var(--color-text-tertiary);font-weight:var(--font-weight-medium);letter-spacing:.02em}.carousel-details{display:flex;align-items:center;gap:var(--spacing-3);flex-wrap:wrap;justify-content:center}.carousel-id{font-size:var(--font-size-xs);color:var(--color-text-tertiary);font-weight:var(--font-weight-medium)}.carousel-method{font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);padding:2px var(--spacing-2);border-radius:var(--radius-sm);text-transform:uppercase;letter-spacing:.03em}.carousel-method.POST{background:#e8f5ee;color:var(--color-accent-success)}.carousel-method.GET{background:#fff3e0;color:var(--color-accent-warning)}.carousel-method.DELETE{background:#fdeceb;color:var(--color-accent-error)}.carousel-path{font-size:var(--font-size-sm);color:var(--color-text-secondary);max-width:400px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.carousel-time{font-size:var(--font-size-xs);color:var(--color-text-tertiary)}.carousel-element{font-size:var(--font-size-xs);color:var(--color-text-secondary)}.carousel-element-using{color:var(--color-accent-secondary);font-weight:var(--font-weight-medium)}.carousel-element-value{color:var(--color-accent-primary)}.main-inspector{display:flex;flex-direction:column;height:100%;overflow:hidden}.inspector-empty{display:flex;align-items:center;justify-content:center;height:100%;background:var(--color-bg-primary)}.inspector-empty-content{display:flex;flex-direction:column;align-items:center;gap:var(--spacing-4);color:var(--color-text-tertiary)}.inspector-empty-icon{font-size:3rem;opacity:.4}.inspector-empty-text{font-size:var(--font-size-base)}.query-section{background:var(--color-bg-secondary);padding:var(--spacing-4) var(--spacing-5);border-bottom:1px solid var(--color-border);flex-shrink:0}.section-title{color:var(--color-text-primary);font-size:var(--font-size-sm);margin:0 0 var(--spacing-3) 0;font-weight:var(--font-weight-semibold);letter-spacing:.01em}.query-row{display:flex;gap:var(--spacing-2);margin-bottom:var(--spacing-3)}.query-select,.query-input{background:var(--color-bg-primary);color:var(--color-text-primary);border:1px solid var(--color-border);padding:var(--spacing-2) var(--spacing-3);border-radius:var(--radius-lg);font-size:var(--font-size-sm);font-family:var(--font-family);transition:border-color var(--transition-fast)}.query-select:focus,.query-input:focus{outline:none;border-color:var(--color-accent-primary)}.query-select{min-width:170px}.query-input{flex:1}.query-btn{background:var(--color-accent-primary);color:#fff;border:none;padding:var(--spacing-2) var(--spacing-5);border-radius:var(--radius-lg);cursor:pointer;font-weight:var(--font-weight-medium);font-size:var(--font-size-sm);transition:all var(--transition-fast)}.query-btn:hover{background:var(--color-accent-secondary)}.query-result{padding:var(--spacing-2) var(--spacing-3);border-radius:var(--radius-md);font-size:var(--font-size-sm);margin-bottom:var(--spacing-3)}.query-result.success{background:#e8f5ee;color:var(--color-accent-success)}.query-result.error{background:#fdeceb;color:var(--color-accent-error);display:flex;align-items:center;gap:var(--spacing-3)}.error-icon{font-size:var(--font-size-sm)}.error-dismiss{margin-left:auto;background:transparent;border:none;color:var(--color-accent-error);cursor:pointer;font-size:var(--font-size-sm);padding:0;opacity:.6;transition:opacity var(--transition-fast)}.error-dismiss:hover{opacity:1}.element-panel{display:flex;gap:var(--spacing-6);padding-top:var(--spacing-3);border-top:1px solid var(--color-border);margin-top:var(--spacing-3)}.element-details{display:flex;flex-direction:column;gap:var(--spacing-2);min-width:240px}.element-attr{display:flex;gap:var(--spacing-3);font-size:var(--font-size-sm)}.attr-name{color:var(--color-text-tertiary);min-width:55px;font-weight:var(--font-weight-medium)}.attr-value{color:var(--color-text-primary)}.locators-section{flex:1}.locators-section h4{color:var(--color-text-secondary);font-size:var(--font-size-sm);margin:0 0 var(--spacing-2) 0;font-weight:var(--font-weight-medium)}.locators-list{display:flex;flex-direction:column;gap:var(--spacing-1)}.locator-row{display:flex;align-items:center;gap:var(--spacing-3);padding:var(--spacing-2) var(--spacing-3);background:var(--color-bg-primary);border-radius:var(--radius-md);cursor:pointer;transition:all var(--transition-fast);position:relative;border:1px solid transparent}.locator-row:hover{background:var(--color-bg-tertiary);border-color:var(--color-border)}.locator-row.copied{background:#e8f5ee;border-color:#c6e7d4}.locator-strategy{color:var(--color-accent-primary);font-size:var(--font-size-xs);min-width:130px;font-weight:var(--font-weight-medium);font-family:var(--font-mono)}.locator-value{flex:1;font-size:var(--font-size-xs);color:var(--color-text-secondary);word-break:break-all;font-family:var(--font-mono)}.copied-badge{font-size:var(--font-size-xs);color:var(--color-accent-success);font-weight:var(--font-weight-medium)}.content-area{flex:1;display:flex;gap:var(--spacing-4);padding:var(--spacing-4);overflow:hidden;background:var(--color-bg-primary)}.screenshot-section{flex-shrink:0;display:flex;align-items:flex-start;justify-content:center;overflow:auto}.screenshot-image{max-height:100%;max-width:350px;border-radius:var(--radius-xl);box-shadow:var(--shadow-md);object-fit:contain;border:1px solid var(--color-border)}.xml-section{flex:1;display:flex;flex-direction:column;overflow:hidden}.xml-section .section-title{flex-shrink:0;margin-bottom:var(--spacing-3)}.xml-source{flex:1;background:var(--color-bg-secondary);padding:var(--spacing-4);border-radius:var(--radius-lg);font-size:var(--font-size-xs);font-family:var(--font-mono);overflow:auto;white-space:pre;color:var(--color-text-secondary);border:1px solid var(--color-border);margin:0;line-height:1.7}.xml-source::-webkit-scrollbar{width:6px;height:6px}.xml-source::-webkit-scrollbar-track{background:transparent;border-radius:var(--radius-sm)}.xml-source::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--radius-sm)}.xml-source::-webkit-scrollbar-thumb:hover{background:var(--color-text-tertiary)}.app{height:100vh;display:flex;flex-direction:column;background:var(--color-bg-primary);overflow:hidden}.app-main{flex:1;overflow:hidden}:root{--color-bg-primary: #F9F7F3;--color-bg-secondary: #FFFFFF;--color-bg-tertiary: #F0EDE6;--color-bg-elevated: #FFFFFF;--color-accent-primary: #C4682A;--color-accent-secondary: #B05C26;--color-accent-success: #2D7D4F;--color-accent-warning: #B8862E;--color-accent-error: #C4453A;--color-text-primary: #1B1B18;--color-text-secondary: #6B6B64;--color-text-tertiary: #9B9B94;--color-border: #E3DFD7;--color-border-hover: #C4682A;--font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono: "SF Mono", "Menlo", "Monaco", "Consolas", monospace;--font-size-xs: .75rem;--font-size-sm: .8125rem;--font-size-base: .9375rem;--font-size-lg: 1.0625rem;--font-size-xl: 1.25rem;--font-size-2xl: 1.5rem;--font-size-3xl: 2rem;--font-weight-normal: 400;--font-weight-medium: 500;--font-weight-semibold: 600;--font-weight-bold: 700;--spacing-1: .25rem;--spacing-2: .5rem;--spacing-3: .75rem;--spacing-4: 1rem;--spacing-5: 1.25rem;--spacing-6: 1.5rem;--spacing-8: 2rem;--spacing-10: 2.5rem;--spacing-12: 3rem;--radius-sm: .375rem;--radius-md: .5rem;--radius-lg: .75rem;--radius-xl: 1rem;--radius-2xl: 1.25rem;--radius-full: 9999px;--shadow-xs: 0 1px 2px rgba(0, 0, 0, .03);--shadow-sm: 0 1px 3px rgba(0, 0, 0, .05), 0 1px 2px rgba(0, 0, 0, .03);--shadow-md: 0 4px 8px -2px rgba(0, 0, 0, .06), 0 2px 4px -2px rgba(0, 0, 0, .04);--shadow-lg: 0 12px 28px -6px rgba(0, 0, 0, .08), 0 4px 12px -4px rgba(0, 0, 0, .04);--transition-fast: .15s ease;--transition-base: .2s ease;--transition-slow: .3s ease;--z-dropdown: 1000;--z-sticky: 1020;--z-modal: 1050;--z-tooltip: 1080}*{box-sizing:border-box;margin:0;padding:0}body{font-family:var(--font-family);background:var(--color-bg-primary);color:var(--color-text-primary);line-height:1.6;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#root{min-height:100vh}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--radius-full)}::-webkit-scrollbar-thumb:hover{background:var(--color-text-tertiary)}.text-xs{font-size:var(--font-size-xs)}.text-sm{font-size:var(--font-size-sm)}.text-base{font-size:var(--font-size-base)}.text-lg{font-size:var(--font-size-lg)}.text-xl{font-size:var(--font-size-xl)}.text-2xl{font-size:var(--font-size-2xl)}.text-3xl{font-size:var(--font-size-3xl)}.font-normal{font-weight:var(--font-weight-normal)}.font-medium{font-weight:var(--font-weight-medium)}.font-semibold{font-weight:var(--font-weight-semibold)}.font-bold{font-weight:var(--font-weight-bold)}.transition{transition:all var(--transition-base)}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();const Fe=!1,Be=(e,t)=>e===t,Re=Symbol("solid-track"),ee={equals:Be};let we=Ae;const V=1,te=2,xe={owned:null,cleanups:null,context:null,owner:null};var _=null;let oe=null,je=null,w=null,T=null,j=null,ie=0;function z(e,t){const n=w,r=_,i=e.length===0,s=t===void 0?r:t,o=i?xe:{owned:null,cleanups:null,context:s?s.context:null,owner:s},l=i?e:()=>e(()=>Q(()=>J(o)));_=o,w=null;try{return Z(l,!0)}finally{w=n,_=r}}function D(e,t){t=t?Object.assign({},ee,t):ee;const n={value:e,observers:null,observerSlots:null,comparator:t.equals||void 0},r=i=>(typeof i=="function"&&(i=i(n.value)),Se(n,i));return[_e.bind(n),r]}function F(e,t,n){const r=he(e,t,!1,V);Y(r)}function fe(e,t,n){we=Ve;const r=he(e,t,!1,V);r.user=!0,j?j.push(r):Y(r)}function H(e,t,n){n=n?Object.assign({},ee,n):ee;const r=he(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,Y(r),_e.bind(r)}function Q(e){if(w===null)return e();const t=w;w=null;try{return e()}finally{w=t}}function de(e){return _===null||(_.cleanups===null?_.cleanups=[e]:_.cleanups.push(e)),e}function _e(){if(this.sources&&this.state)if(this.state===V)Y(this);else{const e=T;T=null,Z(()=>se(this),!1),T=e}if(w){const e=this.observers?this.observers.length:0;w.sources?(w.sources.push(this),w.sourceSlots.push(e)):(w.sources=[this],w.sourceSlots=[e]),this.observers?(this.observers.push(w),this.observerSlots.push(w.sources.length-1)):(this.observers=[w],this.observerSlots=[w.sources.length-1])}return this.value}function Se(e,t,n){let r=e.value;return(!e.comparator||!e.comparator(r,t))&&(e.value=t,e.observers&&e.observers.length&&Z(()=>{for(let i=0;i<e.observers.length;i+=1){const s=e.observers[i],o=oe&&oe.running;o&&oe.disposed.has(s),(o?!s.tState:!s.state)&&(s.pure?T.push(s):j.push(s),s.observers&&Ce(s)),o||(s.state=V)}if(T.length>1e6)throw T=[],new Error},!1)),t}function Y(e){if(!e.fn)return;J(e);const t=ie;He(e,e.value,t)}function He(e,t,n){let r;const i=_,s=w;w=_=e;try{r=e.fn(t)}catch(o){return e.pure&&(e.state=V,e.owned&&e.owned.forEach(J),e.owned=null),e.updatedAt=n+1,Ee(o)}finally{w=s,_=i}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&"observers"in e?Se(e,r):e.value=r,e.updatedAt=n)}function he(e,t,n,r=V,i){const s={fn:e,state:r,updatedAt:null,owned:null,sources:null,sourceSlots:null,cleanups:null,value:t,owner:_,context:_?_.context:null,pure:n};return _===null||_!==xe&&(_.owned?_.owned.push(s):_.owned=[s]),s}function ne(e){if(e.state===0)return;if(e.state===te)return se(e);if(e.suspense&&Q(e.suspense.inFallback))return e.suspense.effects.push(e);const t=[e];for(;(e=e.owner)&&(!e.updatedAt||e.updatedAt<ie);)e.state&&t.push(e);for(let n=t.length-1;n>=0;n--)if(e=t[n],e.state===V)Y(e);else if(e.state===te){const r=T;T=null,Z(()=>se(e,t[0]),!1),T=r}}function Z(e,t){if(T)return e();let n=!1;t||(T=[]),j?n=!0:j=[],ie++;try{const r=e();return Ue(n),r}catch(r){n||(j=null),T=null,Ee(r)}}function Ue(e){if(T&&(Ae(T),T=null),e)return;const t=j;j=null,t.length&&Z(()=>we(t),!1)}function Ae(e){for(let t=0;t<e.length;t++)ne(e[t])}function Ve(e){let t,n=0;for(t=0;t<e.length;t++){const r=e[t];r.user?e[n++]=r:ne(r)}for(t=0;t<n;t++)ne(e[t])}function se(e,t){e.state=0;for(let n=0;n<e.sources.length;n+=1){const r=e.sources[n];if(r.sources){const i=r.state;i===V?r!==t&&(!r.updatedAt||r.updatedAt<ie)&&ne(r):i===te&&se(r,t)}}}function Ce(e){for(let t=0;t<e.observers.length;t+=1){const n=e.observers[t];n.state||(n.state=te,n.pure?T.push(n):j.push(n),n.observers&&Ce(n))}}function J(e){let t;if(e.sources)for(;e.sources.length;){const n=e.sources.pop(),r=e.sourceSlots.pop(),i=n.observers;if(i&&i.length){const s=i.pop(),o=n.observerSlots.pop();r<i.length&&(s.sourceSlots[o]=r,i[r]=s,n.observerSlots[r]=o)}}if(e.tOwned){for(t=e.tOwned.length-1;t>=0;t--)J(e.tOwned[t]);delete e.tOwned}if(e.owned){for(t=e.owned.length-1;t>=0;t--)J(e.owned[t]);e.owned=null}if(e.cleanups){for(t=e.cleanups.length-1;t>=0;t--)e.cleanups[t]();e.cleanups=null}e.state=0}function Xe(e){return e instanceof Error?e:new Error(typeof e=="string"?e:"Unknown error",{cause:e})}function Ee(e,t=_){throw Xe(e)}const Qe=Symbol("fallback");function ye(e){for(let t=0;t<e.length;t++)e[t]()}function Ke(e,t,n={}){let r=[],i=[],s=[],o=0,l=t.length>1?[]:null;return de(()=>ye(s)),()=>{let c=e()||[],u=c.length,f,a;return c[Re],Q(()=>{let m,v,S,E,U,k,O,g,d;if(u===0)o!==0&&(ye(s),s=[],r=[],i=[],o=0,l&&(l=[])),n.fallback&&(r=[Qe],i[0]=z(C=>(s[0]=C,n.fallback())),o=1);else if(o===0){for(i=new Array(u),a=0;a<u;a++)r[a]=c[a],i[a]=z($);o=u}else{for(S=new Array(u),E=new Array(u),l&&(U=new Array(u)),k=0,O=Math.min(o,u);k<O&&r[k]===c[k];k++);for(O=o-1,g=u-1;O>=k&&g>=k&&r[O]===c[g];O--,g--)S[g]=i[O],E[g]=s[O],l&&(U[g]=l[O]);for(m=new Map,v=new Array(g+1),a=g;a>=k;a--)d=c[a],f=m.get(d),v[a]=f===void 0?-1:f,m.set(d,a);for(f=k;f<=O;f++)d=r[f],a=m.get(d),a!==void 0&&a!==-1?(S[a]=i[f],E[a]=s[f],l&&(U[a]=l[f]),a=v[a],m.set(d,a)):s[f]();for(a=k;a<u;a++)a in S?(i[a]=S[a],s[a]=E[a],l&&(l[a]=U[a],l[a](a))):i[a]=z($);i=i.slice(0,o=u),r=c.slice(0)}return i});function $(m){if(s[a]=m,l){const[v,S]=D(a);return l[a]=S,t(c[a],v)}return t(c[a])}}}function N(e,t){return Q(()=>e(t||{}))}const We=e=>`Stale read from <${e}>.`;function Ge(e){const t="fallback"in e&&{fallback:()=>e.fallback};return H(Ke(()=>e.each,e.children,t||void 0))}function q(e){const t=e.keyed,n=H(()=>e.when,void 0,void 0),r=t?n:H(n,void 0,{equals:(i,s)=>!i==!s});return H(()=>{const i=r();if(i){const s=e.children;return typeof s=="function"&&s.length>0?Q(()=>s(t?i:()=>{if(!Q(r))throw We("Show");return n()})):s}return e.fallback},void 0,void 0)}function Je(e,t,n){let r=n.length,i=t.length,s=r,o=0,l=0,c=t[i-1].nextSibling,u=null;for(;o<i||l<s;){if(t[o]===n[l]){o++,l++;continue}for(;t[i-1]===n[s-1];)i--,s--;if(i===o){const f=s<r?l?n[l-1].nextSibling:n[s-l]:c;for(;l<s;)e.insertBefore(n[l++],f)}else if(s===l)for(;o<i;)(!u||!u.has(t[o]))&&t[o].remove(),o++;else if(t[o]===n[s-1]&&n[l]===t[i-1]){const f=t[--i].nextSibling;e.insertBefore(n[l++],t[o++].nextSibling),e.insertBefore(n[--s],f),t[i]=n[s]}else{if(!u){u=new Map;let a=l;for(;a<s;)u.set(n[a],a++)}const f=u.get(t[o]);if(f!=null)if(l<f&&f<s){let a=o,$=1,m;for(;++a<i&&a<s&&!((m=u.get(t[a]))==null||m!==f+$);)$++;if($>f-l){const v=t[o];for(;l<f;)e.insertBefore(n[l++],v)}else e.replaceChild(n[l++],t[o++])}else o++;else t[o++].remove()}}}const be="_$DX_DELEGATE";function Ye(e,t,n,r={}){let i;return z(s=>{i=s,t===document?e():h(t,e(),t.firstChild?null:void 0,n)},r.owner),()=>{i(),t.textContent=""}}function x(e,t,n,r){let i;const s=()=>{const l=document.createElement("template");return l.innerHTML=e,l.content.firstChild},o=()=>(i||(i=s())).cloneNode(!0);return o.cloneNode=o,o}function Te(e,t=window.document){const n=t[be]||(t[be]=new Set);for(let r=0,i=e.length;r<i;r++){const s=e[r];n.has(s)||(n.add(s),t.addEventListener(s,tt))}}function Ze(e,t,n){n==null?e.removeAttribute(t):e.setAttribute(t,n)}function ze(e,t,n={}){const r=Object.keys(t||{}),i=Object.keys(n);let s,o;for(s=0,o=i.length;s<o;s++){const l=i[s];!l||l==="undefined"||t[l]||($e(e,l,!1),delete n[l])}for(s=0,o=r.length;s<o;s++){const l=r[s],c=!!t[l];!l||l==="undefined"||n[l]===c||!c||($e(e,l,!0),n[l]=c)}return n}function et(e,t,n){return Q(()=>e(t,n))}function h(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!="function")return re(e,t,r,n);F(i=>re(e,t(),i,n),r)}function $e(e,t,n){const r=t.trim().split(/\s+/);for(let i=0,s=r.length;i<s;i++)e.classList.toggle(r[i],n)}function tt(e){let t=e.target;const n=`$$${e.type}`,r=e.target,i=e.currentTarget,s=c=>Object.defineProperty(e,"target",{configurable:!0,value:c}),o=()=>{const c=t[n];if(c&&!t.disabled){const u=t[`${n}Data`];if(u!==void 0?c.call(t,u,e):c.call(t,e),e.cancelBubble)return}return t.host&&typeof t.host!="string"&&!t.host._$host&&t.contains(e.target)&&s(t.host),!0},l=()=>{for(;o()&&(t=t._$host||t.parentNode||t.host););};if(Object.defineProperty(e,"currentTarget",{configurable:!0,get(){return t||document}}),e.composedPath){const c=e.composedPath();s(c[0]);for(let u=0;u<c.length-2&&(t=c[u],!!o());u++){if(t._$host){t=t._$host,l();break}if(t.parentNode===i)break}}else l();s(r)}function re(e,t,n,r,i){for(;typeof n=="function";)n=n();if(t===n)return n;const s=typeof t,o=r!==void 0;if(e=o&&n[0]&&n[0].parentNode||e,s==="string"||s==="number"){if(s==="number"&&(t=t.toString(),t===n))return n;if(o){let l=n[0];l&&l.nodeType===3?l.data!==t&&(l.data=t):l=document.createTextNode(t),n=W(e,n,r,l)}else n!==""&&typeof n=="string"?n=e.firstChild.data=t:n=e.textContent=t}else if(t==null||s==="boolean")n=W(e,n,r);else{if(s==="function")return F(()=>{let l=t();for(;typeof l=="function";)l=l();n=re(e,l,n,r)}),()=>n;if(Array.isArray(t)){const l=[],c=n&&Array.isArray(n);if(ue(l,t,n,i))return F(()=>n=re(e,l,n,r,!0)),()=>n;if(l.length===0){if(n=W(e,n,r),o)return n}else c?n.length===0?ve(e,l,r):Je(e,n,l):(n&&W(e),ve(e,l));n=l}else if(t.nodeType){if(Array.isArray(n)){if(o)return n=W(e,n,r,t);W(e,n,null,t)}else n==null||n===""||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}}return n}function ue(e,t,n,r){let i=!1;for(let s=0,o=t.length;s<o;s++){let l=t[s],c=n&&n[e.length],u;if(!(l==null||l===!0||l===!1))if((u=typeof l)=="object"&&l.nodeType)e.push(l);else if(Array.isArray(l))i=ue(e,l,c)||i;else if(u==="function")if(r){for(;typeof l=="function";)l=l();i=ue(e,Array.isArray(l)?l:[l],Array.isArray(c)?c:[c])||i}else e.push(l),i=!0;else{const f=String(l);c&&c.nodeType===3&&c.data===f?e.push(c):e.push(document.createTextNode(f))}}return i}function ve(e,t,n=null){for(let r=0,i=t.length;r<i;r++)e.insertBefore(t[r],n)}function W(e,t,n,r){if(n===void 0)return e.textContent="";const i=r||document.createTextNode("");if(t.length){let s=!1;for(let o=t.length-1;o>=0;o--){const l=t[o];if(i!==l){const c=l.parentNode===e;!s&&!o?c?e.replaceChild(i,l):e.insertBefore(i,n):c&&l.remove()}else s=!0}}else e.insertBefore(i,n);return[i]}class nt{async getHistory(){const t=await fetch("/_recorder/api/history");if(!t.ok)throw new Error(`Failed to fetch history: ${t.statusText}`);return t.json()}async clearHistory(){const t=await fetch("/_recorder/api/clear",{method:"POST"});if(!t.ok)throw new Error(`Failed to clear history: ${t.statusText}`)}connectToStream(t){const n=new EventSource("/_recorder/api/stream");return n.onmessage=r=>{try{const i=JSON.parse(r.data);t(i)}catch(i){console.error("Failed to parse SSE event:",i)}},n.onerror=r=>{console.error("SSE connection error:",r)},()=>n.close()}}const ae=new nt;function st(){const[e,t]=D([]),[n,r]=D(!0);async function i(){r(!0);try{const u=await ae.getHistory();t(u)}catch(u){console.error("Failed to load history:",u)}finally{r(!1)}}fe(()=>{const u=ae.connectToStream(f=>{f.type==="init"?(t(f.data),r(!1)):f.type==="interaction"?t(a=>{const $=a.findIndex(m=>m.id===f.data.id);if($>=0){const m=[...a];return m[$]=f.data,m}else return[...a,f.data]}):f.type==="clear"&&t([])});de(u)});async function s(){await ae.clearHistory()}async function o(){await i()}const l=e().filter(u=>u.screenshot);return{interactions:e,loading:n,stats:()=>({total:e().length,actions:l.length}),clearHistory:s,refresh:o}}var rt=x("<button class=carousel-btn>← Previous"),it=x("<div class=carousel-details><span class=carousel-id>#</span><span></span><span class=carousel-path></span><span class=carousel-time>"),lt=x('<div class=carousel-element><span class=carousel-element-using>:</span> "<span class=carousel-element-value></span>"'),ot=x("<div class=carousel-info><div class=carousel-counter>Action <!> of "),at=x("<button class=carousel-btn>Next →"),ct=x("<div class=carousel>"),ut=x("<div class=carousel-empty><span class=carousel-empty-icon>📱</span><span>No actions recorded yet. Connect Appium Inspector to port 4724 and start interacting.");const ft=e=>{const t=H(()=>e.interactions.filter(l=>l.screenshot)),n=H(()=>t()[e.currentIndex]),r=H(()=>t().length),i=()=>{e.currentIndex>0&&e.onNavigate(e.currentIndex-1)},s=()=>{e.currentIndex<r()-1&&e.onNavigate(e.currentIndex+1)},o=()=>{const l=n();return l?new Date(l.timestamp).toLocaleTimeString():""};return(()=>{var l=ct();return h(l,N(q,{get when(){return r()>0},get fallback(){return ut()},get children(){return[(()=>{var c=rt();return c.$$click=i,F(()=>c.disabled=e.currentIndex===0),c})(),(()=>{var c=ot(),u=c.firstChild,f=u.firstChild,a=f.nextSibling;return a.nextSibling,h(u,()=>e.currentIndex+1,a),h(u,r,null),h(c,N(q,{get when(){return n()},get children(){return[(()=>{var $=it(),m=$.firstChild;m.firstChild;var v=m.nextSibling,S=v.nextSibling,E=S.nextSibling;return h(m,()=>n().id,null),h(v,()=>n().method),h(S,()=>n().path),h(E,o),F(U=>ze(v,{"carousel-method":!0,[n().method]:!0},U)),$})(),N(q,{get when(){return n().elementInfo},get children(){var $=lt(),m=$.firstChild,v=m.firstChild,S=m.nextSibling,E=S.nextSibling;return h(m,()=>n().elementInfo.using,v),h(E,()=>n().elementInfo.value),$}})]}}),null),c})(),(()=>{var c=at();return c.$$click=s,F(()=>c.disabled=e.currentIndex===r()-1),c})()]}})),l})()};Te(["click"]);function dt(e){const n=new DOMParser().parseFromString(e,"text/xml"),r=[];function i(s,o="",l=0){if(s.nodeType!==1)return;const c=s.getAttribute("type")||s.tagName,u=parseInt(s.getAttribute("x")||"0"),f=parseInt(s.getAttribute("y")||"0"),a=parseInt(s.getAttribute("width")||"0"),$=parseInt(s.getAttribute("height")||"0"),m=o+"/"+c+"["+(l+1)+"]";r.push({type:c,name:s.getAttribute("name")||"",label:s.getAttribute("label")||"",value:s.getAttribute("value")||"",enabled:s.getAttribute("enabled")==="true",visible:s.getAttribute("visible")==="true",accessible:s.getAttribute("accessible")==="true",x:u,y:f,width:a,height:$,xpath:m,node:s});const v={};for(const S of Array.from(s.children)){const E=S.getAttribute("type")||S.tagName;v[E]=v[E]||0,i(S,m,v[E]),v[E]++}}return n.documentElement&&i(n.documentElement),r}function ce(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function ht(e){const t=[];return e.name&&t.push({strategy:"accessibility id",value:e.name,platform:"ios"}),e.label&&e.label!==e.name&&t.push({strategy:"accessibility id",value:e.label,platform:"ios"}),t.push({strategy:"xpath",value:e.xpath,platform:"generic"}),t.push({strategy:"class name",value:e.type,platform:"generic"}),e.name&&t.push({strategy:"-ios predicate string",value:`name == "${ce(e.name)}"`,platform:"ios"}),e.label&&t.push({strategy:"-ios predicate string",value:`label == "${ce(e.label)}"`,platform:"ios"}),e.name&&t.push({strategy:"-ios class chain",value:`**/${e.type}[\`name == "${ce(e.name)}"\`]`,platform:"ios"}),t}function pt(e){return ht({type:e.type,name:e.name,label:e.label,xpath:e.xpath}).map(t=>({strategy:t.strategy,value:t.value}))}var gt=x('<div class="query-result success">Found <!> element(s)'),mt=x('<div class="query-result error"><span class=error-icon>⚠️</span><span></span><button class=error-dismiss>✕'),yt=x("<div class=element-attr><span class=attr-name>Name:</span><span class=attr-value>"),bt=x("<div class=element-attr><span class=attr-name>Label:</span><span class=attr-value>"),$t=x("<div class=element-panel><div class=element-details><div class=element-attr><span class=attr-name>Type:</span><span class=attr-value></span></div><div class=element-attr><span class=attr-name>Bounds:</span><span class=attr-value>x=<!>, y=<!>, w=<!>, h=</span></div></div><div class=locators-section><h4>Locators (click to copy)</h4><div class=locators-list>"),vt=x('<div class=query-section><h3 class=section-title>Query Tester</h3><div class=query-row><select class=query-select><option value="accessibility id">accessibility id</option><option value=xpath>xpath</option><option value="class name">class name</option><option value="-ios predicate string">-ios predicate string</option><option value="-ios class chain">-ios class chain</option></select><input type=text placeholder="Enter locator value..."class=query-input><button class=query-btn>Find'),wt=x("<img alt=Screenshot class=screenshot-image>"),xt=x("<div class=content-area><div class=screenshot-section></div><div class=xml-section><h3 class=section-title>XML Source</h3><pre class=xml-source>"),_t=x("<div class=main-inspector>"),St=x("<div class=inspector-empty><div class=inspector-empty-content><span class=inspector-empty-icon>🔍</span><span class=inspector-empty-text>Select an action to inspect"),At=x("<span class=copied-badge>Copied!"),Ct=x("<div class=locator-row><span class=locator-strategy></span><span class=locator-value>");const Et=e=>{const[t,n]=D(null),[r,i]=D("accessibility id"),[s,o]=D(""),[l,c]=D([]),[u,f]=D(null),[a,$]=D(null),[m,v]=D(void 0);fe(()=>{e.interaction&&(n(null),o(""),c([]))});const S=()=>{var g;return(g=e.interaction)!=null&&g.source?dt(e.interaction.source):[]},E=()=>{var B;const g=r(),d=s().trim();if($(null),!d)return;const C=S();let I=[];switch(g){case"accessibility id":I=C.filter(b=>b.name===d||b.label===d);break;case"class name":I=C.filter(b=>b.type===d);break;case"xpath":if((B=e.interaction)!=null&&B.source)try{const y=new DOMParser().parseFromString(e.interaction.source,"text/xml"),p=y.evaluate(d,y,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null),L=[];for(let P=0;P<p.snapshotLength;P++){const X=p.snapshotItem(P);X&&X.nodeType===1&&L.push(X)}I=C.filter(P=>L.some(X=>P.node.isEqualNode(X)))}catch(b){console.error("Invalid XPath expression:",b)}break;case"-ios predicate string":I=C.filter(b=>{const y=d.toLowerCase();if(y.includes("name")){const p=d.match(/name\s*(==|CONTAINS)\s*['"](.*)['"]/i);if(p)return p[1]==="=="?b.name===p[2]:b.name.includes(p[2])}if(y.includes("label")){const p=d.match(/label\s*(==|CONTAINS)\s*['"](.*)['"]/i);if(p)return p[1]==="=="?b.label===p[2]:b.label.includes(p[2])}if(y.includes("type")){const p=d.match(/type\s*(==|CONTAINS)\s*['"](.*)['"]/i);if(p)return p[1]==="=="?b.type===p[2]:b.type.includes(p[2])}return!1});break;case"-ios class chain":const A=d.match(/\*\*\/(\w+)(?:\[`(.+?)`\])?/);if(A){const b=A[1],y=A[2];I=C.filter(p=>{if(p.type!==b)return!1;if(!y)return!0;const L=y.match(/name\s*==\s*['"](.*)['"]/i);if(L)return p.name===L[1];const P=y.match(/label\s*==\s*['"](.*)['"]/i);return P?p.label===P[1]:!0})}break}c(I),I.length>0?(n(I[0]),$(null)):(n(null),$(`No elements found for ${g}: "${d}"`))},U=g=>{navigator.clipboard.writeText(g),f(g),setTimeout(()=>f(null),2e3)},k=()=>{const g=t();return g?pt(g):[]},O=g=>{let d="",C=0;const I=g.replace(/></g,`>
|
|
2
|
+
<`).split(`
|
|
3
|
+
`);for(const B of I){const A=B.trim();A&&(A.startsWith("</")&&(C=Math.max(0,C-1)),d+=" ".repeat(C)+A+`
|
|
4
|
+
`,A.startsWith("<")&&!A.startsWith("</")&&!A.endsWith("/>")&&!A.includes("</")&&C++)}return d};return F(()=>{var d;const g=m();g&&(g.textContent=O(((d=e.interaction)==null?void 0:d.source)||""))}),(()=>{var g=_t();return h(g,N(q,{get when(){return e.interaction},get fallback(){return St()},get children(){return[(()=>{var d=vt(),C=d.firstChild,I=C.nextSibling,B=I.firstChild,A=B.nextSibling,b=A.nextSibling;return B.addEventListener("change",y=>i(y.currentTarget.value)),A.addEventListener("keypress",y=>y.key==="Enter"&&E()),A.$$input=y=>o(y.currentTarget.value),b.$$click=E,h(d,N(q,{get when(){return l().length>0},get children(){var y=gt(),p=y.firstChild,L=p.nextSibling;return L.nextSibling,h(y,()=>l().length,L),y}}),null),h(d,N(q,{get when(){return a()},get children(){var y=mt(),p=y.firstChild,L=p.nextSibling,P=L.nextSibling;return h(L,a),P.$$click=()=>$(null),y}}),null),h(d,N(q,{get when(){return t()},get children(){var y=$t(),p=y.firstChild,L=p.firstChild,P=L.firstChild,X=P.nextSibling,le=L.nextSibling,Ie=le.firstChild,G=Ie.nextSibling,Le=G.firstChild,pe=Le.nextSibling,ke=pe.nextSibling,ge=ke.nextSibling,Oe=ge.nextSibling,me=Oe.nextSibling;me.nextSibling;var Pe=p.nextSibling,Me=Pe.firstChild,qe=Me.nextSibling;return h(X,()=>t().type),h(p,N(q,{get when(){return t().name},get children(){var M=yt(),R=M.firstChild,K=R.nextSibling;return h(K,()=>t().name),M}}),le),h(p,N(q,{get when(){return t().label},get children(){var M=bt(),R=M.firstChild,K=R.nextSibling;return h(K,()=>t().label),M}}),le),h(G,()=>t().x,pe),h(G,()=>t().y,ge),h(G,()=>t().width,me),h(G,()=>t().height,null),h(qe,N(Ge,{get each(){return k()},children:M=>(()=>{var R=Ct(),K=R.firstChild,De=K.nextSibling;return R.$$click=()=>U(M.value),h(K,()=>M.strategy),h(De,()=>M.value),h(R,N(q,{get when(){return u()===M.value},get children(){return At()}}),null),F(()=>R.classList.toggle("copied",u()===M.value)),R})()})),y}}),null),F(()=>B.value=r()),F(()=>A.value=s()),d})(),(()=>{var d=xt(),C=d.firstChild,I=C.nextSibling,B=I.firstChild,A=B.nextSibling;return h(C,N(q,{get when(){return e.interaction.screenshot},get children(){var b=wt();return F(()=>Ze(b,"src",`data:image/png;base64,${e.interaction.screenshot}`)),b}})),et(b=>{v(b),de(()=>{v(void 0)})},A),d})()]}})),g})()};Te(["input","click"]);var Tt=x("<div class=app><main class=app-main>");const Nt=()=>{const{interactions:e}=st(),[t,n]=D(0),r=H(()=>e().filter(s=>s.screenshot)),i=H(()=>r()[t()]);return fe(()=>{const s=r().length;s>0&&n(s-1)}),(()=>{var s=Tt(),o=s.firstChild;return h(s,N(ft,{get interactions(){return e()},get currentIndex(){return t()},onNavigate:n}),o),h(o,N(Et,{get interaction(){return i()}})),s})()},Ne=document.getElementById("root");if(!Ne)throw new Error("Root element not found");Ye(()=>N(Nt,{}),Ne);
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
9
9
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
10
10
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
11
|
+
<script type="module" crossorigin src="/_recorder/assets/index-Cl_X3tPj.js"></script>
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/_recorder/assets/index-CUcJNRfB.css">
|
|
11
13
|
</head>
|
|
12
14
|
<body>
|
|
13
15
|
<div id="root"></div>
|
|
14
|
-
<script type="module" src="/src/index.tsx"></script>
|
|
15
16
|
</body>
|
|
16
17
|
</html>
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium-session-recorder",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Interactive Appium session recorder with modern UI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"appium-recorder": "./
|
|
7
|
+
"appium-recorder": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"engines": {
|
|
10
10
|
"node": ">=18.0.0",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"dev": "bun run src/index.ts",
|
|
26
26
|
"build": "bun run build:ui && bun build src/index.ts --outdir dist --target bun",
|
|
27
27
|
"build:ui": "cd src/ui && bun run build",
|
|
28
|
+
"prepack": "bun run build",
|
|
28
29
|
"test": "vitest run",
|
|
29
30
|
"test:watch": "vitest",
|
|
30
31
|
"test:ui": "vitest run --config vitest.ui.config.ts",
|
|
@@ -58,5 +59,11 @@
|
|
|
58
59
|
"repository": {
|
|
59
60
|
"type": "git",
|
|
60
61
|
"url": "git+https://github.com/JustasMonkev/appium-session-recorder"
|
|
61
|
-
}
|
|
62
|
+
},
|
|
63
|
+
"files": [
|
|
64
|
+
"dist/",
|
|
65
|
+
"skills/",
|
|
66
|
+
"README.md",
|
|
67
|
+
"LICENSE"
|
|
68
|
+
]
|
|
62
69
|
}
|