Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@appetize/playwright

Package Overview
Dependencies
Maintainers
4
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@appetize/playwright - npm Package Compare versions

Comparing version 0.4.0-beta.0 to 0.4.0-beta.1

2

dist/index.umd.js

@@ -18,5 +18,5 @@ (function(m,E){typeof exports=="object"&&typeof module!="undefined"?E(exports,require("events"),require("@playwright/test"),require("fs")):typeof define=="function"&&define.amd?define(["exports","events","@playwright/test","fs"],E):(m=typeof globalThis!="undefined"?globalThis:m||self,E(m.playwright={},m.events,m.test$1,m.fs))})(this,function(m,E,L,B){"use strict";function J(i){return i&&typeof i=="object"&&"default"in i?i:{default:i}}var T=J(B);async function Y(i,{retries:e=3,timeout:t=1e3,predicate:s=()=>!0}){for(let n=1;n<=e;n++)try{return await i()}catch(r){if(n===e||!s(r,n))throw r;await new Promise(o=>setTimeout(o,t))}throw null}function Q(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,i=>{const e=Math.random()*16|0;return(i==="x"?e:e&3|8).toString(16)})}function k(i){return Array.isArray(i)?i.map(k).filter(e=>e!=null):typeof i=="object"&&i!==null?Object.entries(i).reduce((e,[t,s])=>{const n=k(s);return n!=null&&(e[t]=n),e},{}):i}function X(i,e){if("captureStackTrace"in Error)Error.captureStackTrace(i,e);else{const t=new Error;Object.defineProperty(i,"stack",{configurable:!0,get(){const{stack:s}=t;return Object.defineProperty(this,"stack",{value:s}),s}})}}async function h(i,e){i instanceof d&&X(i,e)}class d extends Error{constructor(e){super(e),this.name="Error",this.isOperational=!0,Error.captureStackTrace(this,this.constructor)}}class U extends d{constructor(e){super(`No element found for selector

`)}return a});await T.default.promises.writeFile(e,c.join(`
`)),console.log("\u{1F7E2} Finished"),this.currentRecord+=1}}}function me(i,e){const t=i[i.length-1];if(t)switch(e.type){case"keypress":{(t==null?void 0:t.type)==="keypress"&&!R(e.key)&&!R(t.key)?(i.pop(),i.push({type:"typeText",text:D(t)+D(e)})):(t==null?void 0:t.type)==="typeText"&&!R(e.key)?(i.pop(),i.push({type:"typeText",text:t.text+D(e)})):i.push(e);break}default:i.push(e)}else i.push(e)}function V(i){var t,s,n,r,o,c;let e="";switch(i.type){case"swipe":case"tap":{const a=i.element;return typeof a=="string"?e=` on element "${a}"`:(t=a==null?void 0:a.attributes)!=null&&t.accessibilityIdentifier?e=`element with accessibilityIdentifier "${(s=a.attributes)==null?void 0:s.accessibilityIdentifier}"`:(n=a==null?void 0:a.attributes)!=null&&n.class?e=`element with class "${(r=a.attributes)==null?void 0:r.class}"`:"position"in i&&((o=i.position)==null?void 0:o.x)&&((c=i.position)==null?void 0:c.y)&&(e=`position ${Math.round(i.position.x*100)}%, ${Math.round(i.position.y*100)}%`),e?`${i.type} on ${e}`:i.type}case"keypress":return`type "${D(i)}"`;case"typeText":return`type "${i.text}"`}}function ge({type:i,value:e}){switch(i){case"chromeDevToolsUrl":return{type:"networkInspectorUrl",value:e};case"orientationChanged":return{type:"orientationChanged",value:e}}}const be="0.4.0-beta.0";class ve extends E.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,s)=>{const n=setTimeout(()=>{clearInterval(r),s(new P("Timed out after 60000ms waiting for connection to Appetize page"))},6e4),r=setInterval(()=>{const o=new MessageChannel;o.port1.onmessage=()=>{clearInterval(r),clearTimeout(n),t(!1)},window.postMessage({type:"init",appetizeClient:!0,version:e},"*",[o.port2]),window.__appetize_postMessage=async(c,a=!1)=>{const u=new MessageChannel;if(window.postMessage(c,"*",[u.port2]),a)return new Promise((l,f)=>{const w=setTimeout(()=>{f(new P("Timed out after 60000ms while waiting for postMessage response"))},6e4);u.port1.onmessage=v=>{clearTimeout(w),l(v.data)}})}},100)}),[be]),await this.page.evaluate(()=>{window.__appetize__video_frames=[],window.__appetize__audio_frames=[],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__video_frames.push(e.data.value),!window.__appetize_emit_video)return;break;case"audioData":if(window.__appetize__audio_frames.push(e.data.value),!window.__appetize_emit_audio)return;break}else switch(s){case"frameData":case"recordedAction":case"playbackFoundAndSent":case"playbackNotFound":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 P("Timed out after 60000ms while waiting for Appetize window to be ready.")},6e4)}enableVideoEvents(e=!0){return this.page.evaluate(t=>{window.__appetize_emit_video=t},e)}enableAudioEvents(e=!0){return this.page.evaluate(t=>{window.__appetize_emit_audio=t},e)}async postMessage(e,t=!1){return await this.waitUntilReady(),this.page.evaluate(async([s,n])=>window.__appetize_postMessage(s,n),[e,t])}async getVideoFrames(){return this.page.evaluate(()=>window.__appetize__video_frames)}async getAudioFrames(){return this.page.evaluate(()=>window.__appetize__audio_frames)}async resetVideoFrames(){return this.page.evaluate(()=>{window.__appetize__video_frames=[]})}async resetAudioFrames(){return this.page.evaluate(()=>{window.__appetize__audio_frames=[]})}}class q extends E.EventEmitter{constructor({page:e,type:t,window:s}){super(),this.page=e,this.type=t,this.window=s,this.window.on("*",({type:n,value:r})=>{switch(n){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=ge({type:n,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 A(this,e,t)}}class Ee extends ue{constructor({page:e,config:t,window:s,testInfo:n,deviceInfo:r,sessionInfo:o}){const c=new q({page:e,window:s,type:"appetizer"});super({socket:c,config:t,deviceInfo:r,sessionInfo:o,logger:S}),this.actionLogs=[],this.window=s,this.page=e,this.config=t,this.testInfo=n,this.page.on("load",()=>{this.emit("disconnect")}),t.record&&this.on("disconnect",()=>{this.teardownUi()})}async addActionLog(e){e.error&&(e.ui=await this.getUI({all:!0})),this.actionLogs.push(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([A(this.window,"orientationChanged"),await this.window.postMessage(e==="left"?"rotateLeft":"rotateRight")]);return this.window.page.waitForTimeout(1e3),t}catch(t){throw h(t,this.rotate),t}}async screenshot(e="buffer"){try{const[t]=await Promise.all([A(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 h(t,this.screenshot),t}}async record(){try{if(!this.config.record)throw new d("Recording is not enabled, please enable it by setting `record: true` in session config");if(!this.testInfo)throw new d("session.record() requires using `session` from the test() arguments");return new ye({session:this,testInfo:this.testInfo}).record()}catch(e){throw h(e,this.record),e}}async waitForEvent(e,t){try{return await A(this,e,t)}catch(s){throw h(s,this.waitForEvent),s}}async waitForTimeout(e){try{return await I(e)}catch(t){throw h(t,this.waitForTimeout),t}}async waitForElement(e,t){try{const s=await this.findElements(e,t);if(s.length){if((t==null?void 0:t.matches)&&s.length!==t.matches)throw new Error(`Expected ${t.matches} elements, found ${s.length}`);return s}else throw new Error(`Element not found:
`)),console.log("\u{1F7E2} Finished"),this.currentRecord+=1}}}function me(i,e){const t=i[i.length-1];if(t)switch(e.type){case"keypress":{(t==null?void 0:t.type)==="keypress"&&!R(e.key)&&!R(t.key)?(i.pop(),i.push({type:"typeText",text:D(t)+D(e)})):(t==null?void 0:t.type)==="typeText"&&!R(e.key)?(i.pop(),i.push({type:"typeText",text:t.text+D(e)})):i.push(e);break}default:i.push(e)}else i.push(e)}function V(i){var t,s,n,r,o,c;let e="";switch(i.type){case"swipe":case"tap":{const a=i.element;return typeof a=="string"?e=` on element "${a}"`:(t=a==null?void 0:a.attributes)!=null&&t.accessibilityIdentifier?e=`element with accessibilityIdentifier "${(s=a.attributes)==null?void 0:s.accessibilityIdentifier}"`:(n=a==null?void 0:a.attributes)!=null&&n.class?e=`element with class "${(r=a.attributes)==null?void 0:r.class}"`:"position"in i&&((o=i.position)==null?void 0:o.x)&&((c=i.position)==null?void 0:c.y)&&(e=`position ${Math.round(i.position.x*100)}%, ${Math.round(i.position.y*100)}%`),e?`${i.type} on ${e}`:i.type}case"keypress":return`type "${D(i)}"`;case"typeText":return`type "${i.text}"`}}function ge({type:i,value:e}){switch(i){case"chromeDevToolsUrl":return{type:"networkInspectorUrl",value:e};case"orientationChanged":return{type:"orientationChanged",value:e}}}const be="0.4.0-beta.1";class ve extends E.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,s)=>{const n=setTimeout(()=>{clearInterval(r),s(new P("Timed out after 60000ms waiting for connection to Appetize page"))},6e4),r=setInterval(()=>{const o=new MessageChannel;o.port1.onmessage=()=>{clearInterval(r),clearTimeout(n),t(!1)},window.postMessage({type:"init",appetizeClient:!0,version:e},"*",[o.port2]),window.__appetize_postMessage=async(c,a=!1)=>{const u=new MessageChannel;if(window.postMessage(c,"*",[u.port2]),a)return new Promise((l,f)=>{const w=setTimeout(()=>{f(new P("Timed out after 60000ms while waiting for postMessage response"))},6e4);u.port1.onmessage=v=>{clearTimeout(w),l(v.data)}})}},100)}),[be]),await this.page.evaluate(()=>{window.__appetize__video_frames=[],window.__appetize__audio_frames=[],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__video_frames.push(e.data.value),!window.__appetize_emit_video)return;break;case"audioData":if(window.__appetize__audio_frames.push(e.data.value),!window.__appetize_emit_audio)return;break}else switch(s){case"frameData":case"recordedAction":case"playbackFoundAndSent":case"playbackNotFound":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 P("Timed out after 60000ms while waiting for Appetize window to be ready.")},6e4)}enableVideoEvents(e=!0){return this.page.evaluate(t=>{window.__appetize_emit_video=t},e)}enableAudioEvents(e=!0){return this.page.evaluate(t=>{window.__appetize_emit_audio=t},e)}async postMessage(e,t=!1){return await this.waitUntilReady(),this.page.evaluate(async([s,n])=>window.__appetize_postMessage(s,n),[e,t])}async getVideoFrames(){return this.page.evaluate(()=>window.__appetize__video_frames)}async getAudioFrames(){return this.page.evaluate(()=>window.__appetize__audio_frames)}async resetVideoFrames(){return this.page.evaluate(()=>{window.__appetize__video_frames=[]})}async resetAudioFrames(){return this.page.evaluate(()=>{window.__appetize__audio_frames=[]})}}class q extends E.EventEmitter{constructor({page:e,type:t,window:s}){super(),this.page=e,this.type=t,this.window=s,this.window.on("*",({type:n,value:r})=>{switch(n){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=ge({type:n,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 A(this,e,t)}}class Ee extends ue{constructor({page:e,config:t,window:s,testInfo:n,deviceInfo:r,sessionInfo:o}){const c=new q({page:e,window:s,type:"appetizer"});super({socket:c,config:t,deviceInfo:r,sessionInfo:o,logger:S}),this.actionLogs=[],this.window=s,this.page=e,this.config=t,this.testInfo=n,this.page.on("load",()=>{this.emit("disconnect")}),t.record&&this.on("disconnect",()=>{this.teardownUi()})}async addActionLog(e){e.error&&(e.ui=await this.getUI({all:!0})),this.actionLogs.push(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([A(this.window,"orientationChanged"),await this.window.postMessage(e==="left"?"rotateLeft":"rotateRight")]);return this.window.page.waitForTimeout(1e3),t}catch(t){throw h(t,this.rotate),t}}async screenshot(e="buffer"){try{const[t]=await Promise.all([A(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 h(t,this.screenshot),t}}async record(){try{if(!this.config.record)throw new d("Recording is not enabled, please enable it by setting `record: true` in session config");if(!this.testInfo)throw new d("session.record() requires using `session` from the test() arguments");return new ye({session:this,testInfo:this.testInfo}).record()}catch(e){throw h(e,this.record),e}}async waitForEvent(e,t){try{return await A(this,e,t)}catch(s){throw h(s,this.waitForEvent),s}}async waitForTimeout(e){try{return await I(e)}catch(t){throw h(t,this.waitForTimeout),t}}async waitForElement(e,t){try{const s=await this.findElements(e,t);if(s.length){if((t==null?void 0:t.matches)&&s.length!==t.matches)throw new Error(`Expected ${t.matches} elements, found ${s.length}`);return s}else throw new Error(`Element not found:
${JSON.stringify(e)}`)}catch(s){throw h(s,this.waitForElement),s}}on(e,t){return e==="video"&&(M.onVideo||(this.logger.warn("Listening to the `video` event will significantly slow down your tests. It is recommended to use session.getVideoFrames() instead."),M.onVideo=!0),this.window.enableVideoEvents()),e==="audio"&&(M.onAudio||(this.logger.warn("Listening to the `audio` event will significantly slow down your tests. It is recommended to use session.getAudioFrames() instead."),M.onAudio=!0),this.window.enableAudioEvents()),super.on(e,t)}once(e,t){return e==="video"&&this.window.enableVideoEvents(),e==="audio"&&this.window.enableAudioEvents(),super.once(e,t)}async getVideoFrames(){return await this.window.getVideoFrames()}async getAudioFrames(){return await this.window.getAudioFrames()}}const M={onVideo:!1,onAudio:!1},z=new WeakMap;class xe extends pe{constructor({page:e}){var r;const t=(r=z.get(e))!=null?r:new ve({page:e});z.set(e,t),t.init();const s=new q({type:"webserver",page:e,window:t});super({socket:s,window:t,logger:S}),this.window=t,this.page=e;let n=!1;this.on("queue",({type:o,position:c})=>{n||(n=!0,o==="account"?this.logger.log("All slots for this account are currently in use. Please wait until a slot becomes available."):this.logger.log("All devices are currently in use. Please wait until requested device becomes available.")),c>0&&(o==="account"?this.logger.log(`Position in account-level queue: ${c}`):this.logger.log(`Position in queue: ${c}`))}),this.on("session",()=>{n&&(n=!1)})}validateConfig(e){var s;return{codec:((s=this.page.context().browser())==null?void 0:s.browserType().name())==="chromium"?"jpeg":"h264",...e}}createSession(e,t){return this.session=new Ee({config:e,page:this.page,window:this.window,sessionInfo:t,deviceInfo:this.deviceInfo}),this.session}}class ke{constructor(e){this.queue=null,this.page=e}async start(e){var r,o;const{config:t,baseURL:s}=e,n=new URLSearchParams;t.device&&n.set("device",t.device),t.deviceColor&&n.set("deviceColor",t.deviceColor),t.screenOnly&&n.set("screenOnly",t.screenOnly.toString()),n.set("scale",(o=(r=t.scale)==null?void 0:r.toString())!=null?o:"auto"),await this.page.goto(`${s!=null?s:"https://appetize.io"}/embed/${t.publicKey}?${n.toString()}`),this.client=new xe({page:this.page}),this.client.on("queue",c=>{this.queue=c}),await this.client.waitUntilReady(),this.session=await Y(()=>this.client.startSession({...t}),{retries:5,timeout:3e4,predicate:(c,a)=>c instanceof Error&&c.message.match(/too many requests/)?(console.warn(`Too many session requests. Retrying in 30 seconds... (attempt #${a})`),!0):!1})}}let _,K;const O=L.test.extend({_useConfig:[{},{option:!0}],config:[async({_useConfig:i},e,t)=>{await e({...t.project.use.config,...i,autoplay:!1})},{auto:!0}],_autoSnapshotSuffix:[async({},i,e)=>{e.snapshotSuffix="",await i()},{auto:!0}],appetizePage:async({browser:i,config:e},t)=>{if(_&&JSON.stringify(K)!==JSON.stringify(e)&&(await _.page.close(),await _.page.context().close(),_=null),!_){const s=await i.newContext();if(_=new ke(await s.newPage()),K=e,!e.publicKey)throw new Error('Appetize public key not set. Make sure you have run test.use({ config: { publicKey: "..." } })')}await t(_)},session:async({appetizePage:i,config:e,baseURL:t,_doSetupAndTeardown:s},n,r)=>{if(i.session||await N.step("Start Appetize session",async()=>{await i.start({config:e,baseURL:t})}),!i.session)throw new Error("Appetize session failed to start");i.session.testInfo=r,await n(i.session)},client:async({appetizePage:i},e)=>{await e(i.client)},_doSetupAndTeardown:[async({appetizePage:i},e,t)=>{var s,n;S.clearLogHistory(),i.session&&(i.session.actionLogs=[],await i.session.window.resetVideoFrames(),await i.session.window.resetAudioFrames()),await e(),await j(i,t),t.status==="timedOut"&&((n=(s=i.queue)==null?void 0:s.position)!=null?n:0)>0&&S.warn("Test timed out while in queue for a device. You may increase your test timeout to account for higher queue times.")},{auto:!0}]}),Ae=O.use,H=O.afterEach;Object.assign(O,{setup(i){return{}.__APPETIZE__SETUP_WARNED||S.warn("test.setup() is deprecated and will be removed in a future release. Use test.use({ config: {...} }) instead"),N.use({config:i})},use(i){const{config:e,...t}=i;return Ae({...t,_useConfig:e})},afterEach(i){return H(async({appetizePage:e},t)=>{e&&await j(e,t)}),H(i)}});const N=O,W=new WeakMap;async function j(i,e){if(W.get(e.fn))return;W.set(e.fn,!0);const t=i.session,s="fail-output";if(e.status==="failed"||e.status==="timedOut"){if(t){const o=t.actionLogs;await T.default.promises.mkdir(e.outputPath(s));const c=async()=>{try{const u=await t.screenshot("buffer");e.attach("screenshot",{body:u.data,contentType:"image/png"});const l=e.outputPath(s,"screenshot.png");await T.default.promises.writeFile(l,Buffer.from(u.data))}catch{}},a=async()=>{try{const u=o.map(w=>{if("screenshot"in w){const{screenshot:v,...y}=w;return y}return w});if(!u.length)return;const l=JSON.stringify(u,null,2);e.attach("actions",{body:l,contentType:"application/json"});const f=e.outputPath(s,"actions.json");await T.default.promises.writeFile(f,l)}catch{}};await Promise.all([c(),a()])}await(async()=>{if(!!S.logHistory.length)try{const o=`${S.logHistory.map(a=>`[${a.method}] ${JSON.stringify(a.data).slice(2,-2)}`).join(`
`)}`;e.attach("sdk-logs",{body:o,contentType:"application/text"});const c=e.outputPath(s,"sdk-logs.txt");await T.default.promises.writeFile(c,o)}catch{}})()}}Object.defineProperty(m,"expect",{enumerable:!0,get:function(){return L.expect}}),m.test=N,Object.defineProperties(m,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
//# sourceMappingURL=index.umd.js.map
{
"name": "@appetize/playwright",
"version": "0.4.0-beta.0",
"version": "0.4.0-beta.1",
"description": "Test your mobile apps on Appetize.io with Playwright",

@@ -5,0 +5,0 @@ "files": [

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc