@appetize/playwright
Advanced tools
Comparing version 0.1.8 to 0.2.0
@@ -1216,3 +1216,3 @@ import { EventEmitter } from "events"; | ||
} | ||
const version = "0.1.8"; | ||
const version = "0.2.0"; | ||
const VERSION = version; | ||
@@ -1448,3 +1448,3 @@ class HeadfulClient extends Client { | ||
enableVideoEvents() { | ||
this.page.evaluate(() => { | ||
return this.page.evaluate(() => { | ||
window.__appetize_emit_video = true; | ||
@@ -1454,3 +1454,3 @@ }); | ||
enableAudioEvents() { | ||
this.page.evaluate(() => { | ||
return this.page.evaluate(() => { | ||
window.__appetize_emit_audio = true; | ||
@@ -1460,3 +1460,3 @@ }); | ||
enableRecordEvents() { | ||
this.page.evaluate(() => { | ||
return this.page.evaluate(() => { | ||
window.__appetize_emit_record = true; | ||
@@ -1551,3 +1551,2 @@ }); | ||
const handleAction = (action) => { | ||
sanitizeAction(action); | ||
concatActions(actions, action); | ||
@@ -1669,11 +1668,2 @@ log(describeAction(action)); | ||
} | ||
function sanitizeAction(action) { | ||
switch (action.type) { | ||
case "click": | ||
case "swipe": | ||
delete action.ui; | ||
break; | ||
} | ||
return action; | ||
} | ||
class PlaywrightSession extends Session { | ||
@@ -1680,0 +1670,0 @@ constructor({ |
@@ -34,4 +34,4 @@ (function(d,w){typeof exports=="object"&&typeof module!="undefined"?w(exports,require("events"),require("@playwright/test"),require("fs")):typeof define=="function"&&define.amd?define(["exports","events","@playwright/test","fs"],w):(d=typeof globalThis!="undefined"?globalThis:d||self,w(d.playwright={},d.events,d.test$1,d.fs))})(this,function(d,w,R,W){"use strict";function j(n){return n&&typeof n=="object"&&"default"in n?n:{default:n}}var $=j(W);async function H(n,{retries:e=3,timeout:t=1e3,predicate:s=()=>!0}){for(let i=1;i<=e;i++)try{return await n()}catch(r){if(i===e||!s(r,i))throw r;await new Promise(o=>setTimeout(o,t))}throw null}function U(n,e){switch(n){case"accountQueuedPosition":case"accountQueue":return{type:"queue",value:{type:"account",position:e.position}};case"sessionQueuedPosition":case"queue":return{type:"queue",value:{type:"session",position:e.position}};case"debug":return{type:"log",value:e};case"interceptResponse":return{type:"network",value:{type:"response",...e}};case"interceptRequest":return{type:"network",value:{type:"request",...e}};case"interceptError":return{type:"network",value:{type:"error",...e}};case"userError":return{type:"error",value:e};case"recordedEvent":return e.type==="scrollToElement"?null:{type:"action",value:e};case"userInteractionReceived":return{type:"interaction",value:e};case"countdownWarning":return{type:"inactivityWarning",value:e};case"h264Data":return{type:"video",value:{...e,codec:"h264"}};case"frameData":return{type:"video",value:{...e,codec:"jpeg"}};case"audioData":return{type:"audio",value:{...e,codec:"aac"}};case"deleteEvent":return null;case"newSession":return null}}function D(n){return typeof n=="object"&&n!==null?Object.entries(n).reduce((e,[t,s])=>{const i=D(s);return i!=null&&(e[t]=i),e},{}):n}function J(n,e){if("captureStackTrace"in Error)Error.captureStackTrace(n,e);else{const t=new Error;Object.defineProperty(n,"stack",{configurable:!0,get(){const{stack:s}=t;return Object.defineProperty(this,"stack",{value:s}),s}})}}async function u(n,e){n instanceof f&&J(n,e)}class f extends Error{constructor(e){super(e),this.name=this.constructor.name,this.isOperational=!0,Error.captureStackTrace(this,this.constructor)}}class Y extends f{constructor(e){var i,r,o;const t=(i=e.playback)==null?void 0:i.event;let s=(r=e.message)!=null?r:e.errorId;switch(e.errorId){case"notFound":if(t&&"element"in t){let a=!1;const c=typeof t.element=="object"?{...t.element}:t.element;typeof c=="object"&&"allowMultipleMatches"in c&&(a=!!c.allowMultipleMatches,delete c.allowMultipleMatches),s=`No element${a?"s":""} found for selector | ||
startSession({ enableAdb: true })`);return this.adbConnectionInfo?this.adbConnectionInfo:F(()=>{if(this.adbConnectionInfo)return this.adbConnectionInfo;throw new S("Timed out after 60000ms waiting for adb connection")},6e4)}catch(e){throw u(e,this.getAdbInfo),e}}async rotate(e){try{const[t]=await Promise.all([this.waitForEvent("orientationChanged"),this.socket.send("userInteraction",{type:"keypress",key:e==="left"?"rotateLeft":"rotateRight",timeStamp:Date.now()})]);return t}catch(t){throw u(t,this.rotate),t}}async screenshot(e="buffer"){try{this.socket.send("getScreenshot");const t=await b(this.socket,"screenshot",{timeout:6e4});if(!t.success)throw new f("Screenshot failed");return{data:e==="buffer"?(r=>typeof window=="undefined"?Buffer.from(r):r)(t.data):te(new Uint8Array(t.data),t.mimeType),mimeType:t.mimeType}}catch(t){throw u(t,this.screenshot),t}}async heartbeat(){try{return await this.socket.send("heartbeat")}catch(e){throw u(e,this.heartbeat),e}}async type(e){try{this.config.platform==="ios"&&await T(1e3);const t=[...e].map(X);if(this.config.record)return await this.playAction({type:"keypress",keypress:{type:"keypressArray",shiftKeyArray:t.map(s=>s.shiftKey),keyArray:t.map(s=>s.key),value:e}});await Promise.all([this.socket.send("userInteraction",{type:"keypressArray",shiftKeyArray:t.map(s=>s.shiftKey),keyArray:t.map(s=>s.key),value:e}),this.waitForEvent("interaction",{predicate:s=>s.type==="keypressArray"})])}catch(t){throw u(t,this.type),t}}async keypress(e,t){try{if(e==="ANDROID_KEYCODE_MENU")return await this.socket.send("androidKeycodeMenu");e=G(e);const s=Date.now(),[i]=await Promise.all([this.waitForEvent("interaction",{predicate:r=>r.type==="keypress"&&r.timeStamp===s}),this.socket.send("userInteraction",{type:"keypress",key:e,timeStamp:s,...t})]);return i}catch(s){throw u(s,this.keypress),s}}async setLanguage(e){try{return this.config.language=e,await this.socket.send("setLanguage",{language:e,timeStamp:Date.now()})}catch(t){throw u(t,this.setLanguage),t}}async setLocation(e,t){try{const s=[e.toString(),t.toString()];return this.config.location=s,await this.socket.send("setLocation",{location:s,timeStamp:Date.now()})}catch(s){throw u(s,this.setLocation),s}}async openUrl(e){try{return await this.socket.send("openUrl",{url:e,timeStamp:Date.now()})}catch(t){throw u(t,this.openUrl),t}}async shake(){try{return await this.socket.send("shakeDevice")}catch(e){throw u(e,this.swipe),e}}async biometry({match:e}){try{return await this.socket.send(e?"biometryMatch":"biometryNoMatch")}catch(t){throw u(t,this.biometry),t}}async allowInteractions(e){try{return await this.socket.send(e?"enableInteractions":"disableInteractions")}catch(t){throw u(t,this.allowInteractions),t}}async restartApp(){try{this.socket.send("restartApp");const{platform:e}=this.config;e==="ios"?await this.waitForEvent("appLaunch",{timeout:6e4}):await T(1e3)}catch(e){throw u(e,this.restartApp),e}}async reinstallApp(){try{this.socket.send("reinstallApp"),await this.waitForEvent("appLaunch",{timeout:6e4})}catch(e){throw u(e,this.reinstallApp),e}}async playAction(e,t={}){try{if(!this.config.record)throw new _("playAction()");return this.playActions([e],t).then(s=>s[0])}catch(s){throw u(s,this.playAction),s}}async playActions(e,t={}){try{const{timeout:s=3e4,strictMatch:i}=t,r=[];if(!this.config.record)throw new _("playActions()");for(const o of e){const{id:a,...c}=o;let p=c.type,h="element"in c?c.element:void 0;switch(typeof h=="object"&&(h=D(h)),p){case"tap":p="click";break}const[l]=await Promise.all([new Promise((g,A)=>{const v=()=>{this.off("playbackFoundAndSent",M),this.off("playbackError",P)},M=async x=>{this.actionHistory.push({action:o,result:x}),v(),g(x)},P=x=>{this.actionHistory.push({action:o,error:x}),v(),A(new Y(x))};this.once("playbackFoundAndSent",M),this.once("playbackError",P)}),this.socket.send("playEvent",{event:{...c,element:h,type:p},timeout:Math.round(s/1e3),strictMatch:i,id:a})]);r.push(l)}return r}catch(s){throw u(s,this.playActions),s}}async getUI({timeout:e=3e4}={}){try{this.socket.send("dumpUi");const t=await b(this.socket,"uiDump",{timeout:e});return"ui"in t?t.ui:t.result}catch(t){throw u(t,this.getUI),t}}async findElement(e,{timeout:t,...s}={}){try{const i=await this.playAction({type:"assert",element:e,bundleId:s==null?void 0:s.bundleId},{timeout:t});return i.matchedElements?i.matchedElements[0]:i.matchedElement}catch(i){throw u(i,this.findElement),i}}async findElements(e,t){try{const s=await this.playAction({type:"assert",element:{...e,allowMultipleMatches:!0},bundleId:t==null?void 0:t.bundleId},{timeout:t==null?void 0:t.timeout});return s.matchedElements?s.matchedElements:s.matchedElement?[s.matchedElement]:[]}catch(s){throw u(s,this.findElements),s}}async tap(e,t){try{if("element"in e){if(!this.config.record)throw new _('"element" selector');return await this.playAction({type:"click",element:e.element,bundleId:e.bundleId},{timeout:t==null?void 0:t.timeout})}await this.socket.send("userInteraction",{type:"mousedown",timeStamp:Date.now(),xPos:e.x,yPos:e.y}).then(()=>{this.socket.send("userInteraction",{type:"mouseup",timeStamp:Date.now(),xPos:e.x,yPos:e.y})}),await this.waitForEvent("interaction",{predicate:s=>s.type==="mouseup",timeout:t==null?void 0:t.timeout})}catch(s){throw u(s,this.tap),s}}async swipe(e,t){var s,i;try{if(!this.config.record)throw new _("swipe()");let r;const o=e.element?await this.findElement(e.element):void 0;if(typeof e.gesture=="function"){const a=new K(this,{...e,element:o});e.gesture(a),r=a.toAction()}else{const a=new K(this,{...e,element:o}),c=this.deviceInfo.screen.width*((s=this.deviceInfo.screen.devicePixelRatio)!=null?s:1),p=this.deviceInfo.screen.height*((i=this.deviceInfo.screen.devicePixelRatio)!=null?i:1);switch(e.gesture){case"up":case"down":{const h=p*.5;if(typeof h=="number")a.move(0,h*(e.gesture==="up"?-1:1));else{const l=e.gesture==="up"?"-":"";a.move(0,l+h)}break}case"left":case"right":{const h=c*.5;if(typeof h=="number")a.move(h*(e.gesture==="left"?-1:1),0);else{const l=e.gesture==="left"?"-":"";a.move(l+h,0)}break}}r=a.toAction()}return this.playAction({...r,bundleId:e.bundleId},{timeout:t==null?void 0:t.timeout})}catch(r){throw u(r,this.swipe),r}}}function ne(n){const e="ssh -fN -o StrictHostKeyChecking=no -oHostKeyAlgorithms=+ssh-rsa -p SERVER_PORT USERNAME@HOSTNAME -L6000:FORWARD_DESTINATION:FORWARD_PORT && adb connect localhost:6000";if(!n||!n.forwards[0])return;let t=e;return t=t.replace(/SERVER_PORT/,n.port.toString()),t=t.replace(/USERNAME/,n.user),t=t.replace(/HOSTNAME/,n.hostname),t=t.replace(/FORWARD_DESTINATION/,n.forwards[0].destination),t=t.replace(/FORWARD_PORT/,n.forwards[0].port.toString()),t}const y=function(){const n="[Appetize]";return Function.prototype.bind.call(console.log,console,n)}();class ie extends w.EventEmitter{constructor({socket:e}){super(),this.socket=e,this.socket.on("*",({type:t,value:s})=>{const i=U(t,s);if(i)this.emit(i.type,i.value),this.emit("*",i);else if(i!==null)switch(t){default:this.emit(t,s),this.emit("*",{type:t,value:s})}}),this.socket.on("disconnect",()=>{throw new Error("Client disconnected unexpectedly")})}on(e,t){return super.on(e,t)}async startSession(e){throw new Error("Not implemented")}async config(e){throw new Error("Not implemented")}async waitForSessionStart(e){return new Promise(async(t,s)=>{const i=()=>{s(new Error("Session failed to start - client disconnected"))},r=a=>{s(new Error(`Session failed to start - ${typeof a.message=="object"?JSON.stringify(a.message):a.message}`))},o=a=>{a.message.match(/Too many requests/)&&s(new Error("Session failed to start - too many requests"))};try{this.on("error",o),e.on("disconnect",i),e.on("error",r),await e.waitForEvent("ready",{timeout:null})}finally{this.off("error",o),e.off("disconnect",i),e.off("error",r)}t(e)})}}const O="0.1.8";class re extends ie{constructor({socket:e,window:t}){super({socket:e}),this.window=t,this.window.on("*",async({type:s,value:i})=>{switch(s){case"app":this.app=i,this.emit(s,i);break;case"deviceInfo":this.deviceInfo=i,this.emit(s,i);break;case"config":this._config=this.mapConfig(i);break;case"sessionConnecting":{this.session||(this.session=await this.createSession(this._config));try{await this.waitForSessionStart(this.session),this.emit("session",this.session)}catch{}}}}),this.window.waitUntilReady().then(()=>{this.config({record:!0,apiVersion:O})}),this.getDeviceInfo()}async startSession(e,t){this.deviceInfo||await this.getDeviceInfo();const s=await this.config(e!=null?e:{}),i=await this.createSession(s,t);return await Promise.all([this.window.postMessage({type:"requestSession"},!0),this.waitForSessionStart(i)]),i}async config({publicKey:e,...t}){if(e){const i=await this.window.postMessage({type:"loadApp",value:e},!0);if(i&&"error"in i)throw new Error(i.error)}const s=await this.window.postMessage({type:"setConfig",value:this.validateConfig(t!=null?t:{})},!0).then(this.mapConfig);return this._config=s,s}mapConfig(e){return{...e,device:e.deviceType||e.device}}getDeviceInfo(){return this.window.postMessage({type:"getDeviceInfo"},!0).then(e=>{this.deviceInfo=e})}validateConfig(e){return e}async createSession(e,t){throw new Error("Not implemented")}}function oe({type:n,value:e}){switch(n){case"chromeDevToolsUrl":return{type:"networkInspectorUrl",value:e};case"orientationChanged":return{type:"orientationChanged",value:e}}}class ae extends w.EventEmitter{constructor({page:e}){super(),this.ready=!1,this.page=e,this.page.exposeFunction("__appetize_on",t=>{const s=t==="string"?t:t.type;this.emit(s,t.value),this.emit("*",{type:s,value:t.value})})}async init(){this.ready=!1,await this.page.evaluate(async([e])=>new Promise(t=>{const s=setTimeout(()=>{throw new S("Timed out after 60000ms waiting for connection to Appetize page")},6e4),i=setInterval(()=>{const r=new MessageChannel;r.port1.onmessage=()=>{clearInterval(i),clearTimeout(s),t(!1)},window.postMessage({type:"init",appetizeClient:!0,version:e},"*",[r.port2]),window.__appetize_postMessage=async(o,a=!1)=>{const c=new MessageChannel;if(window.postMessage(o,"*",[c.port2]),a)return new Promise((p,h)=>{const l=setTimeout(()=>{h(new S("Timed out after 60000ms while waiting for postMessage response"))},6e4);c.port1.onmessage=g=>{clearTimeout(l),p(g.data)}})}},100)}),[O]),await this.page.evaluate(()=>{window.addEventListener("message",e=>{var t;if(e.source===window){const s=typeof e.data=="string"?e.data:(t=e.data)==null?void 0:t.type;if(s==="socketEvent")switch(e.data.value.type){case"h264Data":case"frameData":if(!window.__appetize_emit_video)return;break;case"audioData":if(!window.__appetize_emit_audio)return;break;case"recordedEvent":if(!window.__appetize_emit_record)return;break}else switch(s){case"frameData":case"recordedEvent":case"playbackFoundAndSent":case"playbackNotFound":case"deleteEvent":case"debug":case"interceptRequest":case"interceptResponse":case"interceptError":case"uiDump":return}window.__appetize_on(e.data)}})},[]),this.ready=!0}async waitUntilReady(){return F(async()=>{if(!this.ready)throw new S("Timed out after 60000ms while waiting for Appetize window to be ready.")},6e4)}enableVideoEvents(){this.page.evaluate(()=>{window.__appetize_emit_video=!0})}enableAudioEvents(){this.page.evaluate(()=>{window.__appetize_emit_audio=!0})}enableRecordEvents(){this.page.evaluate(()=>{window.__appetize_emit_record=!0})}async postMessage(e,t=!1){return await this.waitUntilReady(),this.page.evaluate(async([s,i])=>window.__appetize_postMessage(s,i),[e,t])}}class L extends w.EventEmitter{constructor({page:e,type:t,window:s}){super(),this.page=e,this.type=t,this.window=s,this.window.on("*",({type:i,value:r})=>{switch(i){case"socketEvent":r.socket===this.type&&(this.emit(r.type,r.value),this.emit("*",{type:r.type,value:r.value}));break;case"disconnect":this.emit("disconnect"),this.emit("*",{type:"disconnect"});break;case"sessionInfo":case"chromeDevToolsUrl":case"orientationChanged":if(this.type==="appetizer"){const o=oe({type:i,value:r});o&&(this.emit(o.type,o.value),this.emit("*",o))}break}})}async send(e,t){return this.window.postMessage({type:"emitSocketEvent",value:{type:e,value:t,socket:this.type}})}async disconnect(){await this.send("disconnect")}waitForEvent(e,t){return b(this,e,t)}}async function ce(n){await n.pause()}class ue{constructor({testInfo:e,session:t}){this.currentRecord=0,this.session=t,this.testInfo=e}async record(){const e=this.testInfo.file,t=await $.default.promises.readFile(e,"utf8"),i=t.split(` | ||
`).map((r,o)=>({line:r,num:o+1})).slice(this.testInfo.line).filter(({line:r})=>r.includes("session.record()"))[this.currentRecord].num;if(i!==void 0){y(`\u{1F534} Recording at line ${i}`);const r=[],o=c=>{le(c),he(r,c),y(V(c))};this.session.on("action",o),await ce(this.session.page),await T(2e3),this.session.off("action",o);const a=t.split(` | ||
startSession({ enableAdb: true })`);return this.adbConnectionInfo?this.adbConnectionInfo:F(()=>{if(this.adbConnectionInfo)return this.adbConnectionInfo;throw new S("Timed out after 60000ms waiting for adb connection")},6e4)}catch(e){throw u(e,this.getAdbInfo),e}}async rotate(e){try{const[t]=await Promise.all([this.waitForEvent("orientationChanged"),this.socket.send("userInteraction",{type:"keypress",key:e==="left"?"rotateLeft":"rotateRight",timeStamp:Date.now()})]);return t}catch(t){throw u(t,this.rotate),t}}async screenshot(e="buffer"){try{this.socket.send("getScreenshot");const t=await b(this.socket,"screenshot",{timeout:6e4});if(!t.success)throw new f("Screenshot failed");return{data:e==="buffer"?(r=>typeof window=="undefined"?Buffer.from(r):r)(t.data):te(new Uint8Array(t.data),t.mimeType),mimeType:t.mimeType}}catch(t){throw u(t,this.screenshot),t}}async heartbeat(){try{return await this.socket.send("heartbeat")}catch(e){throw u(e,this.heartbeat),e}}async type(e){try{this.config.platform==="ios"&&await T(1e3);const t=[...e].map(X);if(this.config.record)return await this.playAction({type:"keypress",keypress:{type:"keypressArray",shiftKeyArray:t.map(s=>s.shiftKey),keyArray:t.map(s=>s.key),value:e}});await Promise.all([this.socket.send("userInteraction",{type:"keypressArray",shiftKeyArray:t.map(s=>s.shiftKey),keyArray:t.map(s=>s.key),value:e}),this.waitForEvent("interaction",{predicate:s=>s.type==="keypressArray"})])}catch(t){throw u(t,this.type),t}}async keypress(e,t){try{if(e==="ANDROID_KEYCODE_MENU")return await this.socket.send("androidKeycodeMenu");e=G(e);const s=Date.now(),[i]=await Promise.all([this.waitForEvent("interaction",{predicate:r=>r.type==="keypress"&&r.timeStamp===s}),this.socket.send("userInteraction",{type:"keypress",key:e,timeStamp:s,...t})]);return i}catch(s){throw u(s,this.keypress),s}}async setLanguage(e){try{return this.config.language=e,await this.socket.send("setLanguage",{language:e,timeStamp:Date.now()})}catch(t){throw u(t,this.setLanguage),t}}async setLocation(e,t){try{const s=[e.toString(),t.toString()];return this.config.location=s,await this.socket.send("setLocation",{location:s,timeStamp:Date.now()})}catch(s){throw u(s,this.setLocation),s}}async openUrl(e){try{return await this.socket.send("openUrl",{url:e,timeStamp:Date.now()})}catch(t){throw u(t,this.openUrl),t}}async shake(){try{return await this.socket.send("shakeDevice")}catch(e){throw u(e,this.swipe),e}}async biometry({match:e}){try{return await this.socket.send(e?"biometryMatch":"biometryNoMatch")}catch(t){throw u(t,this.biometry),t}}async allowInteractions(e){try{return await this.socket.send(e?"enableInteractions":"disableInteractions")}catch(t){throw u(t,this.allowInteractions),t}}async restartApp(){try{this.socket.send("restartApp");const{platform:e}=this.config;e==="ios"?await this.waitForEvent("appLaunch",{timeout:6e4}):await T(1e3)}catch(e){throw u(e,this.restartApp),e}}async reinstallApp(){try{this.socket.send("reinstallApp"),await this.waitForEvent("appLaunch",{timeout:6e4})}catch(e){throw u(e,this.reinstallApp),e}}async playAction(e,t={}){try{if(!this.config.record)throw new _("playAction()");return this.playActions([e],t).then(s=>s[0])}catch(s){throw u(s,this.playAction),s}}async playActions(e,t={}){try{const{timeout:s=3e4,strictMatch:i}=t,r=[];if(!this.config.record)throw new _("playActions()");for(const o of e){const{id:a,...c}=o;let p=c.type,h="element"in c?c.element:void 0;switch(typeof h=="object"&&(h=D(h)),p){case"tap":p="click";break}const[l]=await Promise.all([new Promise((g,A)=>{const v=()=>{this.off("playbackFoundAndSent",M),this.off("playbackError",P)},M=async x=>{this.actionHistory.push({action:o,result:x}),v(),g(x)},P=x=>{this.actionHistory.push({action:o,error:x}),v(),A(new Y(x))};this.once("playbackFoundAndSent",M),this.once("playbackError",P)}),this.socket.send("playEvent",{event:{...c,element:h,type:p},timeout:Math.round(s/1e3),strictMatch:i,id:a})]);r.push(l)}return r}catch(s){throw u(s,this.playActions),s}}async getUI({timeout:e=3e4}={}){try{this.socket.send("dumpUi");const t=await b(this.socket,"uiDump",{timeout:e});return"ui"in t?t.ui:t.result}catch(t){throw u(t,this.getUI),t}}async findElement(e,{timeout:t,...s}={}){try{const i=await this.playAction({type:"assert",element:e,bundleId:s==null?void 0:s.bundleId},{timeout:t});return i.matchedElements?i.matchedElements[0]:i.matchedElement}catch(i){throw u(i,this.findElement),i}}async findElements(e,t){try{const s=await this.playAction({type:"assert",element:{...e,allowMultipleMatches:!0},bundleId:t==null?void 0:t.bundleId},{timeout:t==null?void 0:t.timeout});return s.matchedElements?s.matchedElements:s.matchedElement?[s.matchedElement]:[]}catch(s){throw u(s,this.findElements),s}}async tap(e,t){try{if("element"in e){if(!this.config.record)throw new _('"element" selector');return await this.playAction({type:"click",element:e.element,bundleId:e.bundleId},{timeout:t==null?void 0:t.timeout})}await this.socket.send("userInteraction",{type:"mousedown",timeStamp:Date.now(),xPos:e.x,yPos:e.y}).then(()=>{this.socket.send("userInteraction",{type:"mouseup",timeStamp:Date.now(),xPos:e.x,yPos:e.y})}),await this.waitForEvent("interaction",{predicate:s=>s.type==="mouseup",timeout:t==null?void 0:t.timeout})}catch(s){throw u(s,this.tap),s}}async swipe(e,t){var s,i;try{if(!this.config.record)throw new _("swipe()");let r;const o=e.element?await this.findElement(e.element):void 0;if(typeof e.gesture=="function"){const a=new K(this,{...e,element:o});e.gesture(a),r=a.toAction()}else{const a=new K(this,{...e,element:o}),c=this.deviceInfo.screen.width*((s=this.deviceInfo.screen.devicePixelRatio)!=null?s:1),p=this.deviceInfo.screen.height*((i=this.deviceInfo.screen.devicePixelRatio)!=null?i:1);switch(e.gesture){case"up":case"down":{const h=p*.5;if(typeof h=="number")a.move(0,h*(e.gesture==="up"?-1:1));else{const l=e.gesture==="up"?"-":"";a.move(0,l+h)}break}case"left":case"right":{const h=c*.5;if(typeof h=="number")a.move(h*(e.gesture==="left"?-1:1),0);else{const l=e.gesture==="left"?"-":"";a.move(l+h,0)}break}}r=a.toAction()}return this.playAction({...r,bundleId:e.bundleId},{timeout:t==null?void 0:t.timeout})}catch(r){throw u(r,this.swipe),r}}}function ne(n){const e="ssh -fN -o StrictHostKeyChecking=no -oHostKeyAlgorithms=+ssh-rsa -p SERVER_PORT USERNAME@HOSTNAME -L6000:FORWARD_DESTINATION:FORWARD_PORT && adb connect localhost:6000";if(!n||!n.forwards[0])return;let t=e;return t=t.replace(/SERVER_PORT/,n.port.toString()),t=t.replace(/USERNAME/,n.user),t=t.replace(/HOSTNAME/,n.hostname),t=t.replace(/FORWARD_DESTINATION/,n.forwards[0].destination),t=t.replace(/FORWARD_PORT/,n.forwards[0].port.toString()),t}const y=function(){const n="[Appetize]";return Function.prototype.bind.call(console.log,console,n)}();class ie extends w.EventEmitter{constructor({socket:e}){super(),this.socket=e,this.socket.on("*",({type:t,value:s})=>{const i=U(t,s);if(i)this.emit(i.type,i.value),this.emit("*",i);else if(i!==null)switch(t){default:this.emit(t,s),this.emit("*",{type:t,value:s})}}),this.socket.on("disconnect",()=>{throw new Error("Client disconnected unexpectedly")})}on(e,t){return super.on(e,t)}async startSession(e){throw new Error("Not implemented")}async config(e){throw new Error("Not implemented")}async waitForSessionStart(e){return new Promise(async(t,s)=>{const i=()=>{s(new Error("Session failed to start - client disconnected"))},r=a=>{s(new Error(`Session failed to start - ${typeof a.message=="object"?JSON.stringify(a.message):a.message}`))},o=a=>{a.message.match(/Too many requests/)&&s(new Error("Session failed to start - too many requests"))};try{this.on("error",o),e.on("disconnect",i),e.on("error",r),await e.waitForEvent("ready",{timeout:null})}finally{this.off("error",o),e.off("disconnect",i),e.off("error",r)}t(e)})}}const O="0.2.0";class re extends ie{constructor({socket:e,window:t}){super({socket:e}),this.window=t,this.window.on("*",async({type:s,value:i})=>{switch(s){case"app":this.app=i,this.emit(s,i);break;case"deviceInfo":this.deviceInfo=i,this.emit(s,i);break;case"config":this._config=this.mapConfig(i);break;case"sessionConnecting":{this.session||(this.session=await this.createSession(this._config));try{await this.waitForSessionStart(this.session),this.emit("session",this.session)}catch{}}}}),this.window.waitUntilReady().then(()=>{this.config({record:!0,apiVersion:O})}),this.getDeviceInfo()}async startSession(e,t){this.deviceInfo||await this.getDeviceInfo();const s=await this.config(e!=null?e:{}),i=await this.createSession(s,t);return await Promise.all([this.window.postMessage({type:"requestSession"},!0),this.waitForSessionStart(i)]),i}async config({publicKey:e,...t}){if(e){const i=await this.window.postMessage({type:"loadApp",value:e},!0);if(i&&"error"in i)throw new Error(i.error)}const s=await this.window.postMessage({type:"setConfig",value:this.validateConfig(t!=null?t:{})},!0).then(this.mapConfig);return this._config=s,s}mapConfig(e){return{...e,device:e.deviceType||e.device}}getDeviceInfo(){return this.window.postMessage({type:"getDeviceInfo"},!0).then(e=>{this.deviceInfo=e})}validateConfig(e){return e}async createSession(e,t){throw new Error("Not implemented")}}function oe({type:n,value:e}){switch(n){case"chromeDevToolsUrl":return{type:"networkInspectorUrl",value:e};case"orientationChanged":return{type:"orientationChanged",value:e}}}class ae extends w.EventEmitter{constructor({page:e}){super(),this.ready=!1,this.page=e,this.page.exposeFunction("__appetize_on",t=>{const s=t==="string"?t:t.type;this.emit(s,t.value),this.emit("*",{type:s,value:t.value})})}async init(){this.ready=!1,await this.page.evaluate(async([e])=>new Promise(t=>{const s=setTimeout(()=>{throw new S("Timed out after 60000ms waiting for connection to Appetize page")},6e4),i=setInterval(()=>{const r=new MessageChannel;r.port1.onmessage=()=>{clearInterval(i),clearTimeout(s),t(!1)},window.postMessage({type:"init",appetizeClient:!0,version:e},"*",[r.port2]),window.__appetize_postMessage=async(o,a=!1)=>{const c=new MessageChannel;if(window.postMessage(o,"*",[c.port2]),a)return new Promise((p,h)=>{const l=setTimeout(()=>{h(new S("Timed out after 60000ms while waiting for postMessage response"))},6e4);c.port1.onmessage=g=>{clearTimeout(l),p(g.data)}})}},100)}),[O]),await this.page.evaluate(()=>{window.addEventListener("message",e=>{var t;if(e.source===window){const s=typeof e.data=="string"?e.data:(t=e.data)==null?void 0:t.type;if(s==="socketEvent")switch(e.data.value.type){case"h264Data":case"frameData":if(!window.__appetize_emit_video)return;break;case"audioData":if(!window.__appetize_emit_audio)return;break;case"recordedEvent":if(!window.__appetize_emit_record)return;break}else switch(s){case"frameData":case"recordedEvent":case"playbackFoundAndSent":case"playbackNotFound":case"deleteEvent":case"debug":case"interceptRequest":case"interceptResponse":case"interceptError":case"uiDump":return}window.__appetize_on(e.data)}})},[]),this.ready=!0}async waitUntilReady(){return F(async()=>{if(!this.ready)throw new S("Timed out after 60000ms while waiting for Appetize window to be ready.")},6e4)}enableVideoEvents(){return this.page.evaluate(()=>{window.__appetize_emit_video=!0})}enableAudioEvents(){return this.page.evaluate(()=>{window.__appetize_emit_audio=!0})}enableRecordEvents(){return this.page.evaluate(()=>{window.__appetize_emit_record=!0})}async postMessage(e,t=!1){return await this.waitUntilReady(),this.page.evaluate(async([s,i])=>window.__appetize_postMessage(s,i),[e,t])}}class L extends w.EventEmitter{constructor({page:e,type:t,window:s}){super(),this.page=e,this.type=t,this.window=s,this.window.on("*",({type:i,value:r})=>{switch(i){case"socketEvent":r.socket===this.type&&(this.emit(r.type,r.value),this.emit("*",{type:r.type,value:r.value}));break;case"disconnect":this.emit("disconnect"),this.emit("*",{type:"disconnect"});break;case"sessionInfo":case"chromeDevToolsUrl":case"orientationChanged":if(this.type==="appetizer"){const o=oe({type:i,value:r});o&&(this.emit(o.type,o.value),this.emit("*",o))}break}})}async send(e,t){return this.window.postMessage({type:"emitSocketEvent",value:{type:e,value:t,socket:this.type}})}async disconnect(){await this.send("disconnect")}waitForEvent(e,t){return b(this,e,t)}}async function ce(n){await n.pause()}class ue{constructor({testInfo:e,session:t}){this.currentRecord=0,this.session=t,this.testInfo=e}async record(){const e=this.testInfo.file,t=await $.default.promises.readFile(e,"utf8"),i=t.split(` | ||
`).map((r,o)=>({line:r,num:o+1})).slice(this.testInfo.line).filter(({line:r})=>r.includes("session.record()"))[this.currentRecord].num;if(i!==void 0){y(`\u{1F534} Recording at line ${i}`);const r=[],o=c=>{he(r,c),y(V(c))};this.session.on("action",o),await ce(this.session.page),await T(2e3),this.session.off("action",o);const a=t.split(` | ||
`).map((c,p)=>{var h,l;if(p===i-1){const g=(l=(h=c.match(/^\s*/))==null?void 0:h[0])!=null?l:0;return`${r.map(v=>V(v)).reduce((v,M,P)=>`${v} | ||
@@ -42,5 +42,5 @@ // ${P+1}. ${M}`,"// Recorded using session.record()")} | ||
`)}return c});await $.default.promises.writeFile(e,a.join(` | ||
`)),y("\u{1F7E2} Finished"),this.currentRecord+=1}}}function he(n,e){const t=n[n.length-1];if(t)switch(e.type){case"keypress":(t==null?void 0:t.type)==="keypress"&&e.type==="keypress"&&e.keypress.type==="keypress"?t.keypress.type==="keypress"?n[n.length-1]={...t,keypress:{type:"keypressArray",shiftKeyArray:[t.keypress.shiftKey,e.keypress.shiftKey],keyArray:[t.keypress.key,e.keypress.key],value:C(t.keypress)+C(e.keypress)}}:n[n.length-1]={...t,keypress:{type:"keypressArray",shiftKeyArray:[...t.keypress.shiftKeyArray,e.keypress.shiftKey],keyArray:[...t.keypress.keyArray,e.keypress.key],value:t.keypress.value+C(e.keypress)}}:n.push(e);break;default:n.push(e)}else n.push(e)}function V(n){let e="";switch(n.type){case"swipe":case"click":{const t=n.element;return typeof t=="string"?e=` on element "${t}"`:t!=null&&t.accessibilityIdentifier?e=`element with accessibilityIdentifier "${t.accessibilityIdentifier}"`:t!=null&&t.class?e=`element with class "${t.class}"`:n.xPos&&n.yPos&&(e=`position ${n.xPos}, ${n.yPos}`),e?`${n.type} on ${e}`:n.type}case"keypress":return n.keypress.type==="keypress"?`type "${C(n.keypress)}"`:`type "${n.keypress.value}"`;default:return n.type}}function le(n){switch(n.type){case"click":case"swipe":delete n.ui;break}return n}class pe extends se{constructor({page:e,config:t,window:s,testInfo:i,deviceInfo:r}){const o=new L({page:e,window:s,type:"appetizer"});super({socket:o,config:t,deviceInfo:r}),this.window=s,this.page=e,this.config=t,this.testInfo=i,this.page.on("load",()=>{this.emit("disconnect")}),t.record&&this.on("disconnect",()=>{this.teardownUi()})}async getUI(e={}){return await super.getUI(e)}teardownUi(){return this.window.page.evaluate(()=>{const e=document.querySelector("app-ui");e&&e.remove()})}async rotate(e){try{const[t]=await Promise.all([b(this.window,"orientationChanged"),await this.window.postMessage(e==="left"?"rotateLeft":"rotateRight")]);return this.window.page.waitForTimeout(1e3),t}catch(t){throw u(t,this.rotate),t}}async screenshot(e="buffer"){try{const[t]=await Promise.all([b(this.socket,"screenshot",{timeout:6e4}),this.socket.send("getScreenshot")]),s=new Uint8Array(Object.values(t.data).map(Number));return{data:e==="buffer"?Buffer.from(s):t.data,mimeType:t.mimeType}}catch(t){throw u(t,this.screenshot),t}}async record(){try{if(!this.config.record)throw new f("Recording is not enabled, please enable it by setting `record: true` in session config");if(!this.testInfo)throw new f("session.record() requires using `session` from the test() arguments");return new ue({session:this,testInfo:this.testInfo}).record()}catch(e){throw u(e,this.record),e}}async waitForEvent(e,t){try{return await b(this,e,t)}catch(s){throw u(s,this.waitForEvent),s}}async waitForTimeout(e){try{return await T(e)}catch(t){throw u(t,this.waitForTimeout),t}}async waitForElement(e,t){const s=await this.findElements(e,t);if(typeof(t==null?void 0:t.matches)=="number"?s.length===t.matches:s.length>0)return s;throw new Error(`Element not found: | ||
${JSON.stringify(e)}`)}on(e,t){return e==="video"&&this.window.enableVideoEvents(),e==="audio"&&this.window.enableAudioEvents(),e==="action"&&this.window.enableRecordEvents(),super.on(e,t)}once(e,t){return e==="video"&&this.window.enableVideoEvents(),e==="audio"&&this.window.enableAudioEvents(),e==="action"&&this.window.enableRecordEvents(),super.once(e,t)}}const q=new WeakMap;class de extends re{constructor({page:e}){var r;const t=(r=q.get(e))!=null?r:new ae({page:e});q.set(e,t),t.init();const s=new L({type:"webserver",page:e,window:t});super({socket:s,window:t}),this.window=t,this.page=e;let i=!1;this.on("queue",({type:o,position:a})=>{i||(i=!0,y(o==="account"?"All slots for this account are currently in use. Please wait until a slot becomes available.":"All devices are currently in use. Please wait until requested device becomes available.")),a>0&&y(o==="account"?`Position in account-level queue: ${a}`:`Position in queue: ${a}`)}),this.on("session",()=>{i&&(y("Session started"),i=!1)})}validateConfig(e){var s;return{codec:((s=this.page.context().browser())==null?void 0:s.browserType().name())==="chromium"?"jpeg":"h264",record:!0,apiVersion:O,...e}}async startSession({testInfo:e,...t}){return super.startSession(t,{testInfo:e})}async createSession(e,t){return this.session=new pe({config:e,page:this.page,window:this.window,testInfo:t.testInfo,deviceInfo:this.deviceInfo}),this.session}}R.expect.extend({toHaveElement:async(n,e,t={})=>{try{const s=await n.findElements(e,t);return{pass:typeof t.matches=="number"?s.length===t.matches:s.length>0,message:()=>`Element not found: | ||
${JSON.stringify(e)}`}}catch(s){return{pass:!1,message:()=>s.message}}}});let k,E,m;const I=Object.assign(R.test.extend({_autoSnapshotSuffix:[async({},n,e)=>{e.snapshotSuffix="",await n()},{auto:!0}],page:async({},n)=>{if(!E)throw new Error("Appetize not initialized. Make sure you have run test.setup()");await n(E.page)},session:async({},n)=>{if(!m)throw new Error("Session was not started. Make sure you have run test.setup()");await n(m)},client:async({},n)=>{if(!E)throw new Error("Appetize not initialized. Make sure you have run test.setup()");await n(E)}}),{setup(n){I.afterEach(async({session:e},t)=>{}),I.beforeAll(async({browser:e,baseURL:t},s)=>{var i,r;if(s.config.fullyParallel)throw new Error("fullyParallel is not allowed when running Appetize tests. Please set `fullyParallel: false` in your Playwright config");if(I.setTimeout(6e4*5),k||(k=await e.newPage(),k.on("close",()=>{k=null,E=null,m=null})),"url"in n)await k.goto(n.url);else{const o=new URLSearchParams;n.device&&o.set("device",n.device),n.deviceColor&&o.set("deviceColor",n.deviceColor),n.screenOnly&&o.set("screenOnly",n.screenOnly.toString()),o.set("scale",(r=(i=n.scale)==null?void 0:i.toString())!=null?r:"auto"),await k.goto(`${t!=null?t:"https://appetize.io"}/embed/${n.publicKey}?${o.toString()}`)}E=new de({page:k}),m=await H(()=>E.startSession({...n,testInfo:s}),{retries:5,timeout:3e4,predicate:(o,a)=>o instanceof Error&&o.message.match(/too many requests/)?(console.warn(`Too many session requests. Retrying in 30 seconds... (attempt #${a})`),!0):!1})}),I.afterAll(async({},e)=>{m!=null&&m.page&&await m.page.context().close()})}});Object.defineProperty(d,"expect",{enumerable:!0,get:function(){return R.expect}}),d.test=I,Object.defineProperties(d,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); | ||
`)),y("\u{1F7E2} Finished"),this.currentRecord+=1}}}function he(n,e){const t=n[n.length-1];if(t)switch(e.type){case"keypress":(t==null?void 0:t.type)==="keypress"&&e.type==="keypress"&&e.keypress.type==="keypress"?t.keypress.type==="keypress"?n[n.length-1]={...t,keypress:{type:"keypressArray",shiftKeyArray:[t.keypress.shiftKey,e.keypress.shiftKey],keyArray:[t.keypress.key,e.keypress.key],value:C(t.keypress)+C(e.keypress)}}:n[n.length-1]={...t,keypress:{type:"keypressArray",shiftKeyArray:[...t.keypress.shiftKeyArray,e.keypress.shiftKey],keyArray:[...t.keypress.keyArray,e.keypress.key],value:t.keypress.value+C(e.keypress)}}:n.push(e);break;default:n.push(e)}else n.push(e)}function V(n){let e="";switch(n.type){case"swipe":case"click":{const t=n.element;return typeof t=="string"?e=` on element "${t}"`:t!=null&&t.accessibilityIdentifier?e=`element with accessibilityIdentifier "${t.accessibilityIdentifier}"`:t!=null&&t.class?e=`element with class "${t.class}"`:n.xPos&&n.yPos&&(e=`position ${n.xPos}, ${n.yPos}`),e?`${n.type} on ${e}`:n.type}case"keypress":return n.keypress.type==="keypress"?`type "${C(n.keypress)}"`:`type "${n.keypress.value}"`;default:return n.type}}class le extends se{constructor({page:e,config:t,window:s,testInfo:i,deviceInfo:r}){const o=new L({page:e,window:s,type:"appetizer"});super({socket:o,config:t,deviceInfo:r}),this.window=s,this.page=e,this.config=t,this.testInfo=i,this.page.on("load",()=>{this.emit("disconnect")}),t.record&&this.on("disconnect",()=>{this.teardownUi()})}async getUI(e={}){return await super.getUI(e)}teardownUi(){return this.window.page.evaluate(()=>{const e=document.querySelector("app-ui");e&&e.remove()})}async rotate(e){try{const[t]=await Promise.all([b(this.window,"orientationChanged"),await this.window.postMessage(e==="left"?"rotateLeft":"rotateRight")]);return this.window.page.waitForTimeout(1e3),t}catch(t){throw u(t,this.rotate),t}}async screenshot(e="buffer"){try{const[t]=await Promise.all([b(this.socket,"screenshot",{timeout:6e4}),this.socket.send("getScreenshot")]),s=new Uint8Array(Object.values(t.data).map(Number));return{data:e==="buffer"?Buffer.from(s):t.data,mimeType:t.mimeType}}catch(t){throw u(t,this.screenshot),t}}async record(){try{if(!this.config.record)throw new f("Recording is not enabled, please enable it by setting `record: true` in session config");if(!this.testInfo)throw new f("session.record() requires using `session` from the test() arguments");return new ue({session:this,testInfo:this.testInfo}).record()}catch(e){throw u(e,this.record),e}}async waitForEvent(e,t){try{return await b(this,e,t)}catch(s){throw u(s,this.waitForEvent),s}}async waitForTimeout(e){try{return await T(e)}catch(t){throw u(t,this.waitForTimeout),t}}async waitForElement(e,t){const s=await this.findElements(e,t);if(typeof(t==null?void 0:t.matches)=="number"?s.length===t.matches:s.length>0)return s;throw new Error(`Element not found: | ||
${JSON.stringify(e)}`)}on(e,t){return e==="video"&&this.window.enableVideoEvents(),e==="audio"&&this.window.enableAudioEvents(),e==="action"&&this.window.enableRecordEvents(),super.on(e,t)}once(e,t){return e==="video"&&this.window.enableVideoEvents(),e==="audio"&&this.window.enableAudioEvents(),e==="action"&&this.window.enableRecordEvents(),super.once(e,t)}}const q=new WeakMap;class pe extends re{constructor({page:e}){var r;const t=(r=q.get(e))!=null?r:new ae({page:e});q.set(e,t),t.init();const s=new L({type:"webserver",page:e,window:t});super({socket:s,window:t}),this.window=t,this.page=e;let i=!1;this.on("queue",({type:o,position:a})=>{i||(i=!0,y(o==="account"?"All slots for this account are currently in use. Please wait until a slot becomes available.":"All devices are currently in use. Please wait until requested device becomes available.")),a>0&&y(o==="account"?`Position in account-level queue: ${a}`:`Position in queue: ${a}`)}),this.on("session",()=>{i&&(y("Session started"),i=!1)})}validateConfig(e){var s;return{codec:((s=this.page.context().browser())==null?void 0:s.browserType().name())==="chromium"?"jpeg":"h264",record:!0,apiVersion:O,...e}}async startSession({testInfo:e,...t}){return super.startSession(t,{testInfo:e})}async createSession(e,t){return this.session=new le({config:e,page:this.page,window:this.window,testInfo:t.testInfo,deviceInfo:this.deviceInfo}),this.session}}R.expect.extend({toHaveElement:async(n,e,t={})=>{try{const s=await n.findElements(e,t);return{pass:typeof t.matches=="number"?s.length===t.matches:s.length>0,message:()=>`Element not found: | ||
${JSON.stringify(e)}`}}catch(s){return{pass:!1,message:()=>s.message}}}});let k,E,m;const I=Object.assign(R.test.extend({_autoSnapshotSuffix:[async({},n,e)=>{e.snapshotSuffix="",await n()},{auto:!0}],page:async({},n)=>{if(!E)throw new Error("Appetize not initialized. Make sure you have run test.setup()");await n(E.page)},session:async({},n)=>{if(!m)throw new Error("Session was not started. Make sure you have run test.setup()");await n(m)},client:async({},n)=>{if(!E)throw new Error("Appetize not initialized. Make sure you have run test.setup()");await n(E)}}),{setup(n){I.afterEach(async({session:e},t)=>{}),I.beforeAll(async({browser:e,baseURL:t},s)=>{var i,r;if(s.config.fullyParallel)throw new Error("fullyParallel is not allowed when running Appetize tests. Please set `fullyParallel: false` in your Playwright config");if(I.setTimeout(6e4*5),k||(k=await e.newPage(),k.on("close",()=>{k=null,E=null,m=null})),"url"in n)await k.goto(n.url);else{const o=new URLSearchParams;n.device&&o.set("device",n.device),n.deviceColor&&o.set("deviceColor",n.deviceColor),n.screenOnly&&o.set("screenOnly",n.screenOnly.toString()),o.set("scale",(r=(i=n.scale)==null?void 0:i.toString())!=null?r:"auto"),await k.goto(`${t!=null?t:"https://appetize.io"}/embed/${n.publicKey}?${o.toString()}`)}E=new pe({page:k}),m=await H(()=>E.startSession({...n,testInfo:s}),{retries:5,timeout:3e4,predicate:(o,a)=>o instanceof Error&&o.message.match(/too many requests/)?(console.warn(`Too many session requests. Retrying in 30 seconds... (attempt #${a})`),!0):!1})}),I.afterAll(async({},e)=>{m!=null&&m.page&&await m.page.context().close()})}});Object.defineProperty(d,"expect",{enumerable:!0,get:function(){return R.expect}}),d.test=I,Object.defineProperties(d,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); | ||
//# sourceMappingURL=index.umd.js.map |
@@ -14,3 +14,3 @@ import { PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, TestType } from '@playwright/test'; | ||
} | ||
type SetupOptions = ({ | ||
export type SetupOptions = ({ | ||
publicKey: string; | ||
@@ -17,0 +17,0 @@ } | { |
export * from '../../core/actions'; | ||
export { type NetworkRequest, type NetworkResponse } from '../../core/session'; | ||
export { expect } from '@playwright/test'; | ||
export { test } from './fixture'; | ||
export { test, type SetupOptions } from './fixture'; | ||
export type { PlaywrightClient } from './client'; | ||
export type { PlaywrightSession } from './session'; |
@@ -15,5 +15,5 @@ /// <reference types="node" /> | ||
waitUntilReady(): Promise<void>; | ||
enableVideoEvents(): void; | ||
enableAudioEvents(): void; | ||
enableRecordEvents(): void; | ||
enableVideoEvents(): Promise<void>; | ||
enableAudioEvents(): Promise<void>; | ||
enableRecordEvents(): Promise<void>; | ||
postMessage<T>(data: any, waitForResponse?: boolean): Promise<T>; | ||
@@ -20,0 +20,0 @@ } |
{ | ||
"name": "@appetize/playwright", | ||
"version": "0.1.8", | ||
"version": "0.2.0", | ||
"description": "Test your mobile apps on Appetize.io with Playwright", | ||
@@ -5,0 +5,0 @@ "files": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
402905
2925