@appetize/playwright
Advanced tools
Comparing version 1.0.3-beta.2 to 1.0.3
@@ -18,5 +18,5 @@ var ie=(d,w,b)=>{if(!w.has(d))throw TypeError("Cannot "+b)};var _=(d,w,b)=>(ie(d,w,"read from private field"),b?b.call(d):w.get(d)),j=(d,w,b)=>{if(w.has(d))throw TypeError("Cannot add the same private member more than once");w instanceof WeakSet?w.add(d):w.set(d,b)},B=(d,w,b,M)=>(ie(d,w,"write to private field"),M?M.call(d,b):w.set(d,b),b);(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,b,M){var A,$;"use strict";function ne(i){return i&&typeof i=="object"&&"default"in i?i:{default:i}}var F=ne(M);async function re(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 oe(){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 ae(i){return Object.entries(i).map(([e,t])=>`${e}=${encodeURIComponent(t)}`).join("&")}function x(i){return Array.isArray(i)?i.map(x).filter(e=>e!=null):typeof i=="object"&&i!==null?Object.entries(i).reduce((e,[t,s])=>{const n=x(s);return n!=null&&(e[t]=n),e},{}):i}function J(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 l(i,e){i instanceof f&&J(i,e)}class f extends Error{constructor(e){super(e),this.name="Error",this.isOperational=!0,J(this,this.constructor)}}class ce extends f{constructor(e){super(`No element found for selector | ||
`)}return c});await F.default.promises.writeFile(e,a.join(` | ||
`)),console.log("\u{1F7E2} Finished"),this.currentRecord+=1}}}function $e(i,e){const t=i[i.length-1];if(t)switch(e.type){case"keypress":{(t==null?void 0:t.type)==="keypress"&&!z(e.key)&&!z(t.key)?(i.pop(),i.push({type:"typeText",text:V(t)+V(e)})):(t==null?void 0:t.type)==="typeText"&&!z(e.key)?(i.pop(),i.push({type:"typeText",text:t.text+V(e)})):i.push(e);break}default:i.push(e)}else i.push(e)}function Y(i){var t,s,n,r,o,a;let e="";switch(i.type){case"swipe":case"tap":{const c=i.element;return typeof c=="string"?e=` on element "${c}"`:(t=c==null?void 0:c.attributes)!=null&&t.accessibilityIdentifier?e=`element with accessibilityIdentifier "${(s=c.attributes)==null?void 0:s.accessibilityIdentifier}"`:(n=c==null?void 0:c.attributes)!=null&&n.class?e=`element with class "${(r=c.attributes)==null?void 0:r.class}"`:"position"in i&&((o=i.position)==null?void 0:o.x)&&((a=i.position)==null?void 0:a.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 "${V(i)}"`;case"typeText":return`type "${i.text}"`}}function Q({type:i,value:e}){switch(i){case"deviceInfo":return{type:"deviceInfo",value:e};case"sessionRequested":return{type:"sessionRequested"};case"chromeDevToolsUrl":return{type:"networkInspectorUrl",value:e};case"orientationChanged":return{type:"orientationChanged",value:e}}}const Ce="1.0.3-beta.2";class Fe 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,s)=>{const n=setTimeout(()=>{clearInterval(r),s(new D("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(a,c=!1)=>{const h=new MessageChannel;if(window.postMessage(a,"*",[h.port2]),c)return new Promise((u,p)=>{const y=setTimeout(()=>{p(new D("Timed out after 60000ms while waiting for postMessage response"))},6e4);h.port1.onmessage=g=>{clearTimeout(y),u(g.data)}})}},100)}),[Ce]),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 H(async()=>{if(!this.ready)throw new D("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 X extends w.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":case"deviceInfo":if(this.type==="appetizer"){const o=Q({type:n,value:r});o&&(this.emit(o.type,o.value),this.emit("*",o))}break;case"sessionRequested":if(this.type==="webserver"){const o=Q({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 S(this,e,t)}}class Ie extends Ee{constructor({page:e,config:t,window:s,testInfo:n,...r}){const o=new X({page:e,window:s,type:"appetizer"});super({...r,socket:o,config:t,logger:T}),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){if(e.error){const t=await this.getUI().catch(this.logger.warn);t&&(e.ui=t)}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([S(this.window,"orientationChanged"),await this.window.postMessage(e==="left"?"rotateLeft":"rotateRight")]);return this.window.page.waitForTimeout(1e3),t}catch(t){throw l(t,this.rotate),t}}async screenshot(e="buffer"){try{const[t]=await Promise.all([S(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 l(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 Pe({session:this,testInfo:this.testInfo}).record()}catch(e){throw l(e,this.record),e}}async waitForEvent(e,t){try{return await S(this,e,t)}catch(s){throw l(s,this.waitForEvent),s}}async waitForTimeout(e){try{return await I(e)}catch(t){throw l(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 $e(i,e){const t=i[i.length-1];if(t)switch(e.type){case"keypress":{(t==null?void 0:t.type)==="keypress"&&!z(e.key)&&!z(t.key)?(i.pop(),i.push({type:"typeText",text:V(t)+V(e)})):(t==null?void 0:t.type)==="typeText"&&!z(e.key)?(i.pop(),i.push({type:"typeText",text:t.text+V(e)})):i.push(e);break}default:i.push(e)}else i.push(e)}function Y(i){var t,s,n,r,o,a;let e="";switch(i.type){case"swipe":case"tap":{const c=i.element;return typeof c=="string"?e=` on element "${c}"`:(t=c==null?void 0:c.attributes)!=null&&t.accessibilityIdentifier?e=`element with accessibilityIdentifier "${(s=c.attributes)==null?void 0:s.accessibilityIdentifier}"`:(n=c==null?void 0:c.attributes)!=null&&n.class?e=`element with class "${(r=c.attributes)==null?void 0:r.class}"`:"position"in i&&((o=i.position)==null?void 0:o.x)&&((a=i.position)==null?void 0:a.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 "${V(i)}"`;case"typeText":return`type "${i.text}"`}}function Q({type:i,value:e}){switch(i){case"deviceInfo":return{type:"deviceInfo",value:e};case"sessionRequested":return{type:"sessionRequested"};case"chromeDevToolsUrl":return{type:"networkInspectorUrl",value:e};case"orientationChanged":return{type:"orientationChanged",value:e}}}const Ce="1.0.3";class Fe 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,s)=>{const n=setTimeout(()=>{clearInterval(r),s(new D("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(a,c=!1)=>{const h=new MessageChannel;if(window.postMessage(a,"*",[h.port2]),c)return new Promise((u,p)=>{const y=setTimeout(()=>{p(new D("Timed out after 60000ms while waiting for postMessage response"))},6e4);h.port1.onmessage=g=>{clearTimeout(y),u(g.data)}})}},100)}),[Ce]),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 H(async()=>{if(!this.ready)throw new D("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 X extends w.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":case"deviceInfo":if(this.type==="appetizer"){const o=Q({type:n,value:r});o&&(this.emit(o.type,o.value),this.emit("*",o))}break;case"sessionRequested":if(this.type==="webserver"){const o=Q({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 S(this,e,t)}}class Ie extends Ee{constructor({page:e,config:t,window:s,testInfo:n,...r}){const o=new X({page:e,window:s,type:"appetizer"});super({...r,socket:o,config:t,logger:T}),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){if(e.error){const t=await this.getUI().catch(this.logger.warn);t&&(e.ui=t)}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([S(this.window,"orientationChanged"),await this.window.postMessage(e==="left"?"rotateLeft":"rotateRight")]);return this.window.page.waitForTimeout(1e3),t}catch(t){throw l(t,this.rotate),t}}async screenshot(e="buffer"){try{const[t]=await Promise.all([S(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 l(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 Pe({session:this,testInfo:this.testInfo}).record()}catch(e){throw l(e,this.record),e}}async waitForEvent(e,t){try{return await S(this,e,t)}catch(s){throw l(s,this.waitForEvent),s}}async waitForTimeout(e){try{return await I(e)}catch(t){throw l(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 l(s,this.waitForElement),s}}on(e,t){return e==="video"&&(q.onVideo||(this.logger.warn("Listening to the `video` event will significantly slow down your tests. It is recommended to use session.getVideoFrames() instead."),q.onVideo=!0),this.window.enableVideoEvents()),e==="audio"&&(q.onAudio||(this.logger.warn("Listening to the `audio` event will significantly slow down your tests. It is recommended to use session.getAudioFrames() instead."),q.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 q={onVideo:!1,onAudio:!1},G=new WeakMap;class De extends _e{constructor({page:e}){var r;const t=(r=G.get(e))!=null?r:new Fe({page:e});G.set(e,t),t.init();const s=new X({type:"webserver",page:e,window:t});super({socket:s,window:t,logger:T}),this.window=t,this.page=e;let n=!1;this.on("queue",o=>{n||(n=!0,o.type==="concurrent"?this.logger.log(`Entered ${o.name}. Please wait until a slot becomes available.`):this.logger.log("All devices are currently in use. Please wait until requested device becomes available.")),o.position>0&&(o.type==="concurrent"?this.logger.log(`Position in ${o.name}: ${o.position}`):this.logger.log(`Position in queue: ${o.position}`))}),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 Ie({config:e,page:this.page,window:this.window,path:t.path,token:t.token,device:this.device,app:this.app}),this.session}}class Re{constructor(e){this.queue=null,this.page=e}async start(e){const{config:t,baseURL:s}=e,{publicKey:n,...r}=t;await this.page.goto(`${s!=null?s:"https://appetize.io"}/embed/${n}?${ae(r)}`),this.client=new De({page:this.page}),this.client.on("queue",o=>{this.queue=o}),await this.client.waitUntilReady(),this.session=await re(()=>this.client.startSession({...t}),{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})}}let P,Z;const K=b.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(P&&JSON.stringify(Z)!==JSON.stringify(e)&&(await P.page.close(),await P.page.context().close(),P=null),!P){const s=await i.newContext();if(P=new Re(await s.newPage()),Z=e,!e.publicKey)throw new Error('Appetize public key not set. Make sure you have run test.use({ config: { publicKey: "..." } })')}await t(P)},session:async({appetizePage:i,config:e,baseURL:t,_doSetupAndTeardown:s},n,r)=>{if(i.session||await W.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;T.clearLogHistory(),i.session&&(i.session.actionLogs=[],await i.session.window.resetVideoFrames(),await i.session.window.resetAudioFrames()),await e(),await se(i,t),t.status==="timedOut"&&((n=(s=i.queue)==null?void 0:s.position)!=null?n:0)>0&&T.warn("Test timed out while in queue for a device. You may increase your test timeout to account for higher queue times.")},{auto:!0}]}),Me=K.use,ee=K.afterEach;Object.assign(K,{setup(i){return{}.__APPETIZE__SETUP_WARNED||T.warn("test.setup() is deprecated and will be removed in a future release. Use test.use({ config: {...} }) instead"),W.use({config:i})},use(i){const{config:e,...t}=i;return Me({...t,_useConfig:e})},afterEach(i){return ee(async({appetizePage:e},t)=>{e&&await se(e,t)}),ee(i)}});const W=K,te=new WeakMap;async function se(i,e){if(te.get(e.fn))return;te.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 F.default.promises.mkdir(e.outputPath(s));const a=async()=>{try{const h=await t.screenshot("buffer");e.attach("screenshot",{body:h.data,contentType:"image/png"});const u=e.outputPath(s,"screenshot.png");await F.default.promises.writeFile(u,Buffer.from(h.data))}catch{}},c=async()=>{try{const h=o.map(y=>{if("screenshot"in y){const{screenshot:g,...v}=y;return v}return y});if(!h.length)return;const u=JSON.stringify(h,null,2);e.attach("actions",{body:u,contentType:"application/json"});const p=e.outputPath(s,"actions.json");await F.default.promises.writeFile(p,u)}catch{}};await Promise.all([a(),c()])}await(async()=>{if(!!T.logHistory.length)try{const o=`${T.logHistory.map(c=>`[${c.method}] ${JSON.stringify(c.data).slice(2,-2)}`).join(` | ||
`)}`;e.attach("sdk-logs",{body:o,contentType:"application/text"});const a=e.outputPath(s,"sdk-logs.txt");await F.default.promises.writeFile(a,o)}catch{}})()}}Object.defineProperty(d,"expect",{enumerable:!0,get:function(){return b.expect}}),d.test=W,Object.defineProperties(d,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); | ||
//# sourceMappingURL=index.umd.js.map |
{ | ||
"name": "@appetize/playwright", | ||
"version": "1.0.3-beta.2", | ||
"version": "1.0.3", | ||
"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
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
2
561640