appium-session-recorder 0.0.2 → 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/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 -64
- 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
|
}
|