@testrelic/playwright-analytics 2.1.2 → 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/index.cjs +11 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -331,6 +331,27 @@ test('API data matches UI', { tag: ['@e2e', '@api'] }, async ({ page, request })
|
|
|
331
331
|
});
|
|
332
332
|
```
|
|
333
333
|
|
|
334
|
+
## Examples
|
|
335
|
+
|
|
336
|
+
Full working examples for E2E, API, and unified testing are available in the [testrelic-sdk-examples](https://github.com/testrelic-ai/testrelic-sdk-examples) repository:
|
|
337
|
+
|
|
338
|
+
| Example | Type | What It Demonstrates |
|
|
339
|
+
|---|---|---|
|
|
340
|
+
| [api-testing](https://github.com/testrelic-ai/testrelic-sdk-examples/tree/main/api-testing) | API only | CRUD operations, API chaining, response assertions, config options, error handling |
|
|
341
|
+
| [unified-testing](https://github.com/testrelic-ai/testrelic-sdk-examples/tree/main/unified-testing) | E2E + API | Browser navigation and API calls in the same test |
|
|
342
|
+
| [wikipedia](https://github.com/testrelic-ai/testrelic-sdk-examples/tree/main/wikipedia) | E2E | Homepage, search, link navigation, media-heavy pages |
|
|
343
|
+
| [flipkart](https://github.com/testrelic-ai/testrelic-sdk-examples/tree/main/flipkart) | E2E | Homepage, product search, product pages |
|
|
344
|
+
| [google](https://github.com/testrelic-ai/testrelic-sdk-examples/tree/main/google) | E2E | Search queries, results navigation |
|
|
345
|
+
|
|
346
|
+
Each example is a standalone project — clone and run:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
git clone https://github.com/testrelic-ai/testrelic-sdk-examples.git
|
|
350
|
+
cd testrelic-sdk-examples/api-testing
|
|
351
|
+
npm install
|
|
352
|
+
npx playwright test
|
|
353
|
+
```
|
|
354
|
+
|
|
334
355
|
## Prerequisites
|
|
335
356
|
|
|
336
357
|
- **Node.js** >= 18
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var crypto=require('crypto'),fs=require('fs'),path=require('path'),core=require('@testrelic/core'),child_process=require('child_process'),test=require('@playwright/test'),perf_hooks=require('perf_hooks');var Et=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],
|
|
2
|
-
`);if(t<1||t>n.length)return null;let s=Math.max(1,t-r),
|
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var crypto=require('crypto'),fs=require('fs'),path=require('path'),core=require('@testrelic/core'),child_process=require('child_process'),test=require('@playwright/test'),perf_hooks=require('perf_hooks');var Et=[/AKIA[A-Z0-9]{16}/g,/Bearer\s+[A-Za-z0-9\-._~+/]+=*/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\sKEY-----[\s\S]*?-----END/g,/\/\/[^:]+:[^@]+@/g],Dt=["authorization","cookie","set-cookie","x-api-key"],Ft=["password","secret","token","apiKey","api_key"];function G(e){let t=Object.create(null);return t.trackApiCalls=e?.trackApiCalls??true,t.captureRequestHeaders=e?.captureRequestHeaders??true,t.captureResponseHeaders=e?.captureResponseHeaders??true,t.captureRequestBody=e?.captureRequestBody??true,t.captureResponseBody=e?.captureResponseBody??true,t.captureAssertions=e?.captureAssertions??true,t.redactHeaders=e?.redactHeaders??[...Dt],t.redactBodyFields=e?.redactBodyFields??[...Ft],t.apiIncludeUrls=e?.apiIncludeUrls??[],t.apiExcludeUrls=e?.apiExcludeUrls??[],Object.freeze(t)}function V(e){if(e!==void 0&&!core.isValidConfig(e))throw core.createError(core.ErrorCode.CONFIG_INVALID,"Invalid reporter configuration");let t=Object.create(null);t.outputPath=e?.outputPath??"./test-results/analytics-timeline.json",t.includeStackTrace=e?.includeStackTrace??false,t.includeCodeSnippets=e?.includeCodeSnippets??true,t.codeContextLines=e?.codeContextLines??3,t.includeNetworkStats=e?.includeNetworkStats??true,t.navigationTypes=e?.navigationTypes??null,t.redactPatterns=[...Et,...e?.redactPatterns??[]],t.testRunId=e?.testRunId??null,t.metadata=e?.metadata??null;let r=t.outputPath;return t.openReport=e?.openReport??true,t.htmlReportPath=e?.htmlReportPath??r.replace(/\.json$/,".html"),t.includeArtifacts=e?.includeArtifacts??true,t.trackApiCalls=e?.trackApiCalls??true,t.quiet=e?.quiet??false,Object.freeze(t)}var F="1.3.0";function J(e,t,r){try{let n=fs.readFileSync(e,"utf-8").split(`
|
|
2
|
+
`);if(t<1||t>n.length)return null;let s=Math.max(1,t-r),o=Math.min(n.length,t+r),i=[];for(let l=s;l<=o;l++){let u=l===t?">":" ",d=String(l).padStart(String(o).length," ");i.push(`${u} ${d} | ${n[l-1]}`);}return i.join(`
|
|
3
3
|
`)}catch{return null}}function Y(e){return t=>{let r=t;for(let a of e)if(typeof a=="string"){let n=a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");r=r.replace(new RegExp(n,"g"),"[REDACTED]");}else {let n=a.flags.includes("g")?a.flags:a.flags+"g",s=new RegExp(a.source,n);r=r.replace(s,"[REDACTED]");}return r}}function Pt(e){return e.GITHUB_ACTIONS!=="true"?null:{provider:"github-actions",buildId:e.GITHUB_RUN_ID??null,commitSha:e.GITHUB_SHA??null,branch:e.GITHUB_REF_NAME??null}}function Ot(e){return e.GITLAB_CI!=="true"?null:{provider:"gitlab-ci",buildId:e.CI_PIPELINE_ID??null,commitSha:e.CI_COMMIT_SHA??null,branch:e.CI_COMMIT_BRANCH??e.CI_COMMIT_REF_NAME??null}}function Ht(e){if(!e.JENKINS_URL)return null;let t=e.GIT_BRANCH??null;return t?.startsWith("origin/")&&(t=t.slice(7)),{provider:"jenkins",buildId:e.BUILD_ID??null,commitSha:e.GIT_COMMIT??null,branch:t}}function zt(e){return e.CIRCLECI!=="true"?null:{provider:"circleci",buildId:e.CIRCLE_BUILD_NUM??null,commitSha:e.CIRCLE_SHA1??null,branch:e.CIRCLE_BRANCH??null}}var Ut=[Pt,Ot,Ht,zt];function Z(e){let t=process.env;for(let r of Ut){let a=r(t);if(a)return a}return null}var K=`
|
|
4
4
|
/* Theme Variables */
|
|
5
5
|
:root,[data-theme="dark"]{
|
|
@@ -1389,13 +1389,13 @@ function _updateCard(cls,val){
|
|
|
1389
1389
|
<script>${jt}</script>
|
|
1390
1390
|
</body>
|
|
1391
1391
|
</html>`}function nt(e){try{let t=process.platform,r;t==="darwin"?r=`open "${e}"`:t==="win32"?r=`start "" "${e}"`:r=`xdg-open "${e}"`,child_process.exec(r,a=>{a&&process.stderr.write(`[testrelic] Failed to open browser: ${a.message}
|
|
1392
|
-
`);});}catch{}}function Kt(e){let t=JSON.stringify(e);return at(t)}function st(e,t){try{let r=Kt(e),a=t.htmlReportPath,n=path.dirname(a);fs.mkdirSync(n,{recursive:!0});let s=a+".tmp";if(fs.writeFileSync(s,r,"utf-8"),fs.renameSync(s,a),t.openReport&&e.ci===null){let
|
|
1393
|
-
`);}}function Wt(e){let t=e.replace(/[^a-zA-Z0-9\-_ ]/g,"-").replace(/\s+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return t.length>100&&(t=t.substring(0,100).replace(/-+$/,"")),t||"unnamed-test"}function dt(e,t,r,a){let n=e.find(
|
|
1394
|
-
`}function ft(e,t,r){if(
|
|
1395
|
-
`,
|
|
1396
|
-
`,
|
|
1397
|
-
`);}if(!w){
|
|
1398
|
-
`);let k=null;if(s==="failed"||s==="flaky"){let h=(s==="flaky"?t.results.find(A=>A.status!=="passed")?.errors??[]:a.errors)[0];if(h){let A=Y(this.config.redactPatterns),b=h.location?.line??null,I=null;this.config.includeCodeSnippets&&b!==null&&h.location?.file&&(I=J(h.location.file,b,this.config.codeContextLines),I&&(I=A(I))),k={message:A(h.message??"Unknown error"),line:b,code:I,stack:this.config.includeStackTrace&&h.stack?A(h.stack):null};}}let m=t.titlePath().filter(Boolean),y=path.relative(this.rootDir||".",t.location.file),
|
|
1399
|
-
`);}}};var Se=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function Ae(e){let t=e.toLowerCase();return Se.some(r=>t.includes(r))}function mt(e,t){let r=new TextEncoder().encode(e);return r.length<=t?{text:e,truncated:false}:{text:new TextDecoder().decode(r.slice(0,t)),truncated:true}}var B=class{constructor(t,r){this.page=t;this.records=[];this.listeners=[];this.currentNetworkCounter=null;this.pendingRequests=new Map;this.capturedRequests=[];this.pendingBodyReads=[];this.requestIdCounter=0;this.requestCaptureCount=0;this.includeNetworkStats=r?.includeNetworkStats??true,this.origGoto=t.goto.bind(t),this.origGoBack=t.goBack.bind(t),this.origGoForward=t.goForward.bind(t),this.origReload=t.reload.bind(t),this.interceptMethods(),this.attachListeners();}async init(){await this.injectSPADetection();}async getCapturedRequests(){await Promise.allSettled(this.pendingBodyReads),this.pendingBodyReads=[];for(let[t,r]of this.pendingRequests)this.capturedRequests.push({url:r.url,method:r.method,resourceType:r.resourceType,statusCode:0,responseTimeMs:Date.now()-r.startTimeMs,startedAt:r.startedAt,requestHeaders:r.headers,requestBody:r.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:r.postDataTruncated,responseBodyTruncated:false,isBinary:false,error:"incomplete"}),this.pendingRequests.delete(t);return [...this.capturedRequests].sort((t,r)=>t.startedAt.localeCompare(r.startedAt))}async getData(){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}});let t=this.records.map(a=>({url:a.url,navigationType:a.navigationType,timestamp:a.timestamp,domContentLoadedAt:a.domContentLoadedAt,networkIdleAt:a.networkIdleAt,networkStats:a.networkStats})),r=this.includeNetworkStats?await this.getCapturedRequests():[];return {navigations:t,networkRequests:r}}async flushLegacyAnnotations(t){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}});for(let r of this.records){let a={url:r.url,navigationType:r.navigationType,timestamp:r.timestamp,domContentLoadedAt:r.domContentLoadedAt,networkIdleAt:r.networkIdleAt,networkStats:r.networkStats};t.annotations.push({type:"lambdatest-navigation",description:JSON.stringify(a)});}if(this.includeNetworkStats){let r=await this.getCapturedRequests();r.length>0&&t.annotations.push({type:"__testrelic_network_requests",description:JSON.stringify(r)});}}dispose(){this.page.goto=this.origGoto,this.page.goBack=this.origGoBack,this.page.goForward=this.origGoForward,this.page.reload=this.origReload;for(let{event:t,handler:r}of this.listeners)this.page.off(t,r);this.listeners=[],this.records=[],this.pendingRequests.clear(),this.capturedRequests=[],this.pendingBodyReads=[],this.requestCaptureCount=0;}getRecords(){return this.records}interceptMethods(){let t=this,r=this.page;r.goto=async function(a,n){return t.recordNavigation(a,"goto"),t.origGoto(a,n)},r.goBack=async function(a){let n=await t.origGoBack(a);return t.recordNavigation(r.url(),"back"),n},r.goForward=async function(a){let n=await t.origGoForward(a);return t.recordNavigation(r.url(),"forward"),n},r.reload=async function(a){return t.recordNavigation(r.url(),"refresh"),t.origReload(a)};}attachListeners(){let t=()=>{this.lastDomContentLoaded=new Date().toISOString(),this.records.length>0&&(this.records[this.records.length-1].domContentLoadedAt=this.lastDomContentLoaded);};this.page.on("domcontentloaded",t),this.listeners.push({event:"domcontentloaded",handler:t});let r=n=>{try{let s=n;if(typeof s.parentFrame=="function"&&s.parentFrame()!==null)return;let i=s.url(),o=this.records[this.records.length-1];if(o&&Date.now()-new Date(o.timestamp).getTime()<50&&o.url===i)return;this.recordNavigation(i,"navigation");}catch{}};this.page.on("framenavigated",r),this.listeners.push({event:"framenavigated",handler:r});let a=n=>{try{let s=n;if(s.type()!=="debug")return;let i=s.text();if(!i.startsWith("__testrelic_nav:"))return;let o=JSON.parse(i.slice(16));o.type&&o.url&&this.recordNavigation(o.url,o.type);}catch{}};if(this.page.on("console",a),this.listeners.push({event:"console",handler:a}),this.includeNetworkStats){let n=o=>{if(this.currentNetworkCounter&&this.currentNetworkCounter.totalRequests++,!(this.requestCaptureCount>=500)){this.requestCaptureCount++;try{let d=o,p=String(this.requestIdCounter++),l=d.postData()??null,f=!1;if(l!==null){let c=mt(l,10240);l=c.text,f=c.truncated;}let g={url:d.url(),method:d.method(),resourceType:this.mapResourceType(d.resourceType()),headers:d.headers(),postData:l,postDataTruncated:f,startedAt:new Date().toISOString(),startTimeMs:Date.now()};this.pendingRequests.set(p,g),o.__testrelic_id=p;}catch{}}};this.page.on("request",n),this.listeners.push({event:"request",handler:n});let s=o=>{try{let d=o;if(this.currentNetworkCounter){let m=d.status();m>=400&&(this.currentNetworkCounter.failedRequests++,this.currentNetworkCounter.failedRequestUrls.push(m+" "+d.url()));let y=d.headers()["content-length"];y&&(this.currentNetworkCounter.totalBytes+=parseInt(y,10)||0);let u=d.request().resourceType(),v=this.mapResourceType(u);this.currentNetworkCounter.byType[v]++;}let p=d.request().__testrelic_id;if(!p)return;let l=this.pendingRequests.get(p);if(!l)return;this.pendingRequests.delete(p);let f=Date.now()-l.startTimeMs,g=d.headers(),c=g["content-type"]??null,w=parseInt(g["content-length"]??"0",10)||0,C=c?!Ae(c):!1,k=(async()=>{let m=null,y=!1;if(!C)try{let T=(await d.body()).toString("utf-8"),S=mt(T,10240);m=S.text,y=S.truncated;}catch{}let u={url:l.url,method:l.method,resourceType:l.resourceType,statusCode:d.status(),responseTimeMs:f,startedAt:l.startedAt,requestHeaders:l.headers,requestBody:l.postData,responseBody:m,responseHeaders:g,contentType:c,responseSize:w,requestBodyTruncated:l.postDataTruncated,responseBodyTruncated:y,isBinary:C,error:null};this.capturedRequests.push(u);})();this.pendingBodyReads.push(k);}catch{}};this.page.on("response",s),this.listeners.push({event:"response",handler:s});let i=o=>{if(this.currentNetworkCounter){this.currentNetworkCounter.failedRequests++;try{let d=o;this.currentNetworkCounter.failedRequestUrls.push("ERR "+d.url());}catch{}}try{let d=o,p=d.__testrelic_id;if(!p)return;let l=this.pendingRequests.get(p);if(!l)return;this.pendingRequests.delete(p);let f={url:l.url,method:l.method,resourceType:l.resourceType,statusCode:0,responseTimeMs:Date.now()-l.startTimeMs,startedAt:l.startedAt,requestHeaders:l.headers,requestBody:l.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:l.postDataTruncated,responseBodyTruncated:!1,isBinary:!1,error:d.failure()?.errorText??"Unknown error"};this.capturedRequests.push(f);}catch{}};this.page.on("requestfailed",i),this.listeners.push({event:"requestfailed",handler:i});}}async injectSPADetection(){try{await this.page.addInitScript(()=>{let t=history.pushState.bind(history),r=history.replaceState.bind(history);history.pushState=function(...a){t(...a),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_route",url:location.href}));},history.replaceState=function(...a){r(...a),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_replace",url:location.href}));},window.addEventListener("popstate",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"popstate",url:location.href}));}),window.addEventListener("hashchange",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"hash_change",url:location.href}));});});}catch{}}recordNavigation(t,r){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}}),this.records.push({url:t,navigationType:r,timestamp:new Date().toISOString()}),this.includeNetworkStats&&(this.currentNetworkCounter=this.createNetworkCounter());}createNetworkCounter(){return {totalRequests:0,failedRequests:0,failedRequestUrls:[],totalBytes:0,byType:{xhr:0,document:0,script:0,stylesheet:0,image:0,font:0,other:0}}}mapResourceType(t){switch(t){case "xhr":case "fetch":return "xhr";case "document":return "document";case "script":return "script";case "stylesheet":return "stylesheet";case "image":return "image";case "font":return "font";default:return "other"}}};var bt=Symbol.for("__testrelic_call_id"),Ne="__testrelic_api_assertions",_=new WeakMap,N=class{constructor(){this.assertions=[];this.currentCallId=null;}recordAssertion(t){this.assertions.push(t);}getAssertions(){return this.assertions}setCurrentCallId(t){this.currentCallId=t;}getCurrentCallId(){return this.currentCallId}getData(){return [...this.assertions]}flushLegacyAnnotations(t){this.assertions.length!==0&&t.annotations.push({type:Ne,description:JSON.stringify(this.assertions)});}dispose(){this.assertions=[],this.currentCallId=null;}};var vt="[REDACTED]";function z(e,t){if(e===null||t.length===0)return e;let r=new Set(t.map(n=>n.toLowerCase())),a={};for(let n of Object.keys(e))Object.hasOwn(e,n)&&(a[n]=r.has(n.toLowerCase())?vt:e[n]);return a}function E(e,t){if(e===null||t.length===0)return e;let r;try{r=JSON.parse(e);}catch{return e}if(typeof r!="object"||r===null)return e;let a=new Set(t),n=H(r,a);return JSON.stringify(n)}function H(e,t){if(Array.isArray(e))return e.map(r=>H(r,t));if(typeof e=="object"&&e!==null){let r={};for(let a of Object.keys(e)){if(!Object.hasOwn(e,a))continue;let n=e[a];t.has(a)?r[a]=vt:r[a]=H(n,t);}return r}return e}function xt(e,t,r){if(r.length>0){for(let a of r)if(yt(e,a))return false}if(t.length>0){for(let a of t)if(yt(e,a))return true;return false}return true}function yt(e,t){try{return t instanceof RegExp?t.test(e):_e(t).test(e)}catch{return console.warn(`[testrelic] Invalid URL filter pattern: ${String(t)}`),false}}function _e(e){let t="",r=0;for(;r<e.length;){let a=e[r];a==="*"&&e[r+1]==="*"?(t+=".*",r+=2,e[r]==="/"&&r++):a==="*"?(t+="[^/]*",r++):a==="?"?(t+="[^/]",r++):".+^${}()|[]\\".includes(a)?(t+="\\"+a,r++):(t+=a,r++);}return new RegExp(t)}var qe=["get","post","put","patch","delete","head","fetch"],Ie=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"],Le="__testrelic_api_calls";function Be(e){let t=e.toLowerCase();return Ie.some(r=>t.includes(r))}function Ee(e){if(!e)return null;if(e.data!==void 0&&e.data!==null){let t=e.data;return typeof t=="string"?t:Buffer.isBuffer(t)?t.toString("base64"):JSON.stringify(t)}if(e.form!==void 0&&e.form!==null)return JSON.stringify(e.form);if(e.multipart!==void 0&&e.multipart!==null){let t=e.multipart,r={};for(let[a,n]of Object.entries(t))typeof n=="string"||typeof n=="number"||typeof n=="boolean"?r[a]=String(n):n&&typeof n=="object"&&"name"in n?r[a]=`[file: ${n.name}]`:r[a]="[binary]";return JSON.stringify(r)}return null}var F=class F{constructor(t,r,a){this.originals=new Map;this.capturedCalls=[];this.callCounter=0;this.disposed=false;this._lastCallId=null;this.primitiveCallIds=new Map;this.context=t,this.assertionTracker=r??null,this.apiConfig=a??F.DEFAULT_API_CONFIG;}get lastCallId(){return this._lastCallId}getCallIdForValue(t){return t!=null&&typeof t=="object"?_.get(t)??null:this.primitiveCallIds.get(t)??null}intercept(){for(let r of qe){let a=this.context[r].bind(this.context);this.originals.set(r,a),this.context[r]=this.createWrapper(r,a);}let t=this.context.dispose.bind(this.context);this.originals.set("dispose",t),this.context.dispose=async r=>(this.disposed=true,t(r));}getData(){return [...this.capturedCalls]}flushLegacyAnnotations(t){this.capturedCalls.length!==0&&t.annotations.push({type:Le,description:JSON.stringify(this.capturedCalls)});}dispose(){for(let[t,r]of this.originals)this.context[t]=r;this.originals.clear(),this.capturedCalls=[],this.callCounter=0,this._lastCallId=null,this.primitiveCallIds.clear();}get isDisposed(){return this.disposed}getCapturedCalls(){return this.capturedCalls}tagResponseMethods(t,r){let a=this,n=t.headers.bind(t);t.headers=function(){let c=n();return _.set(c,r),c};let s=t.headersArray.bind(t);t.headersArray=function(){let c=s();return _.set(c,r),c};let i=t.json.bind(t);t.json=async function(){let c=await i();return c!=null&&typeof c=="object"&&_.set(c,r),c};let o=t.status.bind(t);t.status=function(){let c=o();return a.primitiveCallIds.set(c,r),c};let d=t.statusText.bind(t);t.statusText=function(){let c=d();return a.primitiveCallIds.set(c,r),c};let p=t.ok.bind(t);t.ok=function(){let c=p();return a.primitiveCallIds.set(c,r),c};let l=t.text.bind(t);t.text=async function(){let c=await l();return a.primitiveCallIds.set(c,r),c};let f=t.body.bind(t);t.body=async function(){let c=await f();return _.set(c,r),c};}createWrapper(t,r){let a=this;return async function(s,i){if(!xt(s,a.apiConfig.apiIncludeUrls,a.apiConfig.apiExcludeUrls))return r(s,i);let o=`api-call-${a.callCounter++}`,d=new Date().toISOString(),p=t==="fetch"?(i?.method??"GET").toUpperCase():t.toUpperCase(),l=Ee(i),f=perf_hooks.performance.now();a._lastCallId=o,a.assertionTracker&&a.assertionTracker.setCurrentCallId(o);let g;try{g=await r(s,i);}catch(c){let w=perf_hooks.performance.now();try{let C=a.apiConfig.captureRequestBody?E(l,a.apiConfig.redactBodyFields):null,k={id:o,timestamp:d,method:p,url:s,requestHeaders:null,requestBody:C,responseStatusCode:null,responseStatusText:null,responseHeaders:null,responseBody:null,responseTimeMs:Math.round((w-f)*100)/100,isBinary:!1,error:c instanceof Error?c.message:String(c)};a.capturedCalls.push(k);}catch{}throw c}try{let c=perf_hooks.performance.now(),w=g.headers(),C=w["content-type"]??null,k=C?!Be(C):!1,m=null;a.apiConfig.captureRequestHeaders&&i?.headers&&(m=i.headers);let y=null;a.apiConfig.captureResponseHeaders&&(y=w);let u=a.apiConfig.captureRequestBody?l:null,v=null;if(a.apiConfig.captureResponseBody)try{k?v=(await g.body()).toString("base64"):v=await g.text();}catch{}m=z(m,a.apiConfig.redactHeaders),y=z(y,a.apiConfig.redactHeaders),u=E(u,a.apiConfig.redactBodyFields),v=E(v,a.apiConfig.redactBodyFields);let T={id:o,timestamp:d,method:p,url:g.url(),requestHeaders:m,requestBody:u,responseStatusCode:g.status(),responseStatusText:g.statusText(),responseHeaders:y,responseBody:v,responseTimeMs:Math.round((c-f)*100)/100,isBinary:k,error:null};a.capturedCalls.push(T);}catch{}try{g[bt]=o,a.tagResponseMethods(g,o);}catch{}return g}}};F.DEFAULT_API_CONFIG=Object.freeze({trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]});var q=F;var Me="__testrelic_api_config",De="__testrelic_config_trackApiCalls";function j(e){let t=e.annotations.find(a=>a.type===Me&&a.description!==void 0);if(t)try{return JSON.parse(t.description,Pe)}catch{}let r=e.annotations.find(a=>a.type===De&&a.description!==void 0);return r?{trackApiCalls:r.description!=="false",captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}:{trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}}function Pe(e,t){if(typeof t=="object"&&t!==null&&t.__regexp===true&&typeof t.source=="string"){let{source:r,flags:a}=t;return new RegExp(r,a)}return t}var Tt={page:async({page:e},t,r)=>{let a=new B(e);try{await a.init();}catch{}await t(e);try{let{navigations:n,networkRequests:s}=await a.getData(),i={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:n,networkRequests:s,apiCalls:[],apiAssertions:[]};await r.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(i)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{await a.flushLegacyAnnotations(r);}catch{}a.dispose();},request:async({request:e},t,r)=>{let a=j(r);if(!a.trackApiCalls){await t(e);return}let n=new N,s=new q(e,n,a);s.intercept(),await t(e);try{let i=s.getData(),o=a.captureAssertions?n.getData():[],d={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:i,apiAssertions:o};await r.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(d)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{s.flushLegacyAnnotations(r);}catch{}try{n.flushLegacyAnnotations(r);}catch{}s.dispose(),n.dispose();}};test.test.extend(Tt);var Ue={request:async({request:e},t,r)=>{let a=j(r);if(!a.trackApiCalls){await t(e);return}let n=new N,s=new q(e,n,a);s.intercept(),await t(e);try{let i=s.getData(),o=a.captureAssertions?n.getData():[],d={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:i,apiAssertions:o};await r.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(d)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{s.flushLegacyAnnotations(r);}catch{}try{n.flushLegacyAnnotations(r);}catch{}s.dispose(),n.dispose();}};var Rt=false;function ca(e,t,r="manual_record"){if(!e||!e.annotations){Rt||(Rt=true,process.stderr.write(`[testrelic] recordNavigation: reporter not active, navigation not recorded
|
|
1400
|
-
`));return}let a={url:t,navigationType:r,timestamp:new Date().toISOString()};e.annotations.push({type:"lambdatest-navigation",description:JSON.stringify(a)});}Object.defineProperty(exports,"ATTACHMENT_CONTENT_TYPE",{enumerable:true,get:function(){return core.ATTACHMENT_CONTENT_TYPE}});Object.defineProperty(exports,"ATTACHMENT_NAME",{enumerable:true,get:function(){return core.ATTACHMENT_NAME}});Object.defineProperty(exports,"PAYLOAD_VERSION",{enumerable:true,get:function(){return core.PAYLOAD_VERSION}});Object.defineProperty(exports,"isTestRelicDataPayload",{enumerable:true,get:function(){return core.isTestRelicDataPayload}});exports.SCHEMA_VERSION=
|
|
1392
|
+
`);});}catch{}}function Kt(e){let t=JSON.stringify(e);return at(t)}function st(e,t){try{let r=Kt(e),a=t.htmlReportPath,n=path.dirname(a);fs.mkdirSync(n,{recursive:!0});let s=a+".tmp";if(fs.writeFileSync(s,r,"utf-8"),fs.renameSync(s,a),t.openReport&&e.ci===null){let o=path.resolve(a);nt(o);}}catch(r){process.stderr.write(`[testrelic] Failed to write HTML report: ${r instanceof Error?r.message:String(r)}
|
|
1393
|
+
`);}}function Wt(e){let t=e.replace(/[^a-zA-Z0-9\-_ ]/g,"-").replace(/\s+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return t.length>100&&(t=t.substring(0,100).replace(/-+$/,"")),t||"unnamed-test"}function dt(e,t,r,a){let n=e.find(u=>u.name==="screenshot"&&u.path),s=e.find(u=>u.name==="video"&&u.path);if(!n&&!s)return null;let o=Wt(t);r>0&&(o+=`--retry-${r}`);let i=path.join(a,"artifacts",o),l={};try{fs.mkdirSync(i,{recursive:!0});}catch{return null}if(n?.path)try{if(fs.existsSync(n.path)){let d=`screenshot${path.extname(n.path)||".png"}`;fs.copyFileSync(n.path,path.join(i,d)),l.screenshot=`artifacts/${o}/${d}`;}}catch{}if(s?.path)try{if(fs.existsSync(s.path)){let d=`video${path.extname(s.path)||".webm"}`;fs.copyFileSync(s.path,path.join(i,d)),l.video=`artifacts/${o}/${d}`;}}catch{}return !l.screenshot&&!l.video?null:l}function ut(e,t){let r=[];for(let a of e){let n=Qt(a),s=te(a),o=ee(a,n,s,t),i=re(a,n,s);if(o.length===0&&i.length===0){r.push({type:"navigation",url:"about:blank",timestamp:a.startedAt,durationOnUrl:a.duration,navigationType:"dummy",domContentLoadedAt:null,networkIdleAt:null,networkStats:null,specFile:a.specFile,test:n,tests:[s],_testTitle:a.title});continue}r.push(...o,...i);}return r.sort(ae),ne(r,e),r.map((a,n)=>a.type==="navigation"?{...{index:n,type:"navigation",url:a.url,timestamp:a.timestamp,durationOnUrl:a.durationOnUrl??0,navigationType:a.navigationType,domContentLoadedAt:a.domContentLoadedAt??null,networkIdleAt:a.networkIdleAt??null,networkStats:a.networkStats??null,specFile:a.specFile,test:a.test},tests:a.tests}:{...{index:n,type:"api_call",callId:a.callId,method:a.method,url:a.url,timestamp:a.timestamp,responseTime:a.responseTime??null,request:a.request,response:a.response??null,...a.error?{error:a.error}:{},assertions:a.assertions??[],specFile:a.specFile,test:a.test},tests:a.tests})}function Qt(e){return {title:e.title,fullTitle:e.titlePath,status:e.status,duration:e.duration,retries:e.retryCount,retry:e.retry,tags:e.tags,failure:e.failure}}function te(e){return {title:e.title,status:e.status,duration:e.duration,startedAt:e.startedAt,completedAt:e.completedAt,retryCount:e.retryCount,tags:e.tags,failure:e.failure,testId:e.testId,filePath:e.filePath,suiteName:e.suiteName,testType:e.testType,isFlaky:e.isFlaky,retryStatus:e.retryStatus,expectedStatus:e.expectedStatus,actualStatus:e.actualStatus,artifacts:e.artifacts,networkRequests:e.networkRequests,apiCalls:e.apiCalls,apiAssertions:e.apiAssertions}}function ee(e,t,r,a){let n=[];for(let s of e.navigations)a.navigationTypes!==null&&!a.navigationTypes.includes(s.navigationType)||n.push({type:"navigation",url:s.url,timestamp:s.timestamp,durationOnUrl:0,navigationType:s.navigationType,domContentLoadedAt:s.domContentLoadedAt??null,networkIdleAt:s.networkIdleAt??null,networkStats:s.networkStats??null,specFile:e.specFile,test:t,tests:[r],_testTitle:e.title});return n}function re(e,t,r){if(!e.apiCalls||e.apiCalls.length===0)return [];let a=e.apiAssertions??[];return e.apiCalls.map(n=>{let s=a.filter(i=>i.callId===n.id).map(i=>({type:i.type,expected:i.expected,actual:i.actual,status:i.status,location:i.location,...i.expression!==void 0?{expression:i.expression}:{}})),o=null;return n.responseStatusCode!==null&&n.responseStatusText!==null&&(o={statusCode:n.responseStatusCode,statusText:n.responseStatusText,headers:n.responseHeaders,body:pt(n.responseBody)}),{type:"api_call",callId:n.id,method:n.method,url:n.url,timestamp:n.timestamp,responseTime:n.error?null:n.responseTimeMs,request:{headers:n.requestHeaders,body:pt(n.requestBody)},response:o,...n.error?{error:n.error}:{},assertions:s,specFile:e.specFile,test:t,tests:[r],_testTitle:e.title}})}function ae(e,t){let r=new Date(e.timestamp).getTime(),a=new Date(t.timestamp).getTime();if(r!==a)return r-a;let n={navigation:0,api_call:1},s=n[e.type],o=n[t.type];return s!==o?s-o:e.type==="api_call"&&t.type==="api_call"&&e.callId&&t.callId?ct(e.callId)-ct(t.callId):0}function ct(e){let t=e.match(/(\d+)$/);return t?parseInt(t[1],10):0}function ne(e,t){for(let r=0;r<e.length;r++){let a=e[r];if(a.type!=="navigation")continue;let n=new Date(a.timestamp).getTime(),s=null;for(let o=r+1;o<e.length;o++)if(e[o]._testTitle===a._testTitle){s=new Date(e[o].timestamp).getTime();break}if(s!==null)a.durationOnUrl=Math.max(0,s-n);else {let o=t.find(i=>i.title===a._testTitle);if(o){let i=new Date(o.completedAt).getTime();a.durationOnUrl=Math.max(0,i-n);}}}}function pt(e){if(e==null)return null;try{return JSON.parse(e)}catch{return e}}function P(e,t){let r=e.length,a=Math.min(Math.ceil(t/100*r)-1,r-1);return e[Math.max(0,a)]}function se(e){try{let t=new URL(e);return t.origin+t.pathname}catch{return e}}function ie(e){return e==null?"error":e>=200&&e<300?"2xx":e>=300&&e<400?"3xx":e>=400&&e<500?"4xx":e>=500&&e<600?"5xx":"error"}function gt(e,t){let r=0,a=0,n=0,s=0,o=0;for(let g of e)switch(g.status){case "passed":r++;break;case "failed":a++;break;case "flaky":n++;break;case "skipped":s++;break;case "timedout":o++;break}let i=[];for(let g of e)g.apiCalls&&i.push(...g.apiCalls);let l=i.length,u=new Set,d={},f={"2xx":0,"3xx":0,"4xx":0,"5xx":0,error:0},p=[];for(let g of i)u.add(se(g.url)),d[g.method]=(d[g.method]??0)+1,f[ie(g.responseStatusCode)]+=1,p.push(g.responseTimeMs);let c=null;if(p.length>0){let g=[...p].sort((T,S)=>T-S),v=g.reduce((T,S)=>T+S,0);c={avg:Math.round(v/g.length),min:g[0],max:g[g.length-1],p50:P(g,50),p95:P(g,95),p99:P(g,99)};}let w=0,C=0,k=0;for(let g of e)if(g.apiAssertions)for(let v of g.apiAssertions)w++,v.status==="passed"?C++:k++;let m=0,y=new Set;for(let g of e){m+=g.navigations.length;for(let v of g.navigations)y.add(v.url);}return {total:e.length,passed:r,failed:a,flaky:n,skipped:s,timedout:o,totalApiCalls:l,uniqueApiUrls:u.size,apiCallsByMethod:d,apiCallsByStatusRange:f,apiResponseTime:c,totalAssertions:w,passedAssertions:C,failedAssertions:k,totalNavigations:m,uniqueNavigationUrls:y.size,totalTimelineSteps:t}}function oe(e){let t=56-e.length;return t>0?e+" ".repeat(t):e}function R(e){return `\u2502 ${oe(e)} \u2502
|
|
1394
|
+
`}function ft(e,t,r,a){if(a||e.total===0)return;let n=`\u250C${"\u2500".repeat(58)}\u2510
|
|
1395
|
+
`,s=`\u2514${"\u2500".repeat(58)}\u2518
|
|
1396
|
+
`,o=R(""),i=n;i+=R("TestRelic Timeline Generated"),i+=o;let l=[];if(e.passed>0&&l.push(`${e.passed} \u2713`),e.failed>0&&l.push(`${e.failed} \u2717`),e.flaky>0&&l.push(`${e.flaky} \u26A0`),e.skipped>0&&l.push(`${e.skipped} skipped`),e.timedout>0&&l.push(`${e.timedout} timedout`),i+=R(`Tests: ${e.total} total (${l.join(" ")})`),e.totalNavigations>0&&(i+=R(`Navigations: ${e.totalNavigations} visits across ${e.uniqueNavigationUrls} unique URLs`)),e.totalApiCalls>0){i+=R(`API Calls: ${e.totalApiCalls} calls across ${e.uniqueApiUrls} unique endpoints`);let u=Object.entries(e.apiCallsByMethod).filter(([,f])=>f>0).map(([f,p])=>`${f}: ${p}`);u.length>0&&(i+=R(` ${u.join(" ")}`));let d=Object.entries(e.apiCallsByStatusRange).filter(([,f])=>f>0).map(([f,p])=>`${f}: ${p}`);d.length>0&&(i+=R(` ${d.join(" ")}`)),e.apiResponseTime&&(i+=R(` Avg response: ${e.apiResponseTime.avg}ms P95: ${e.apiResponseTime.p95}ms`));}e.totalAssertions>0&&(i+=R(`Assertions: ${e.totalAssertions} total (${e.passedAssertions} \u2713 ${e.failedAssertions} \u2717)`)),i+=R(`Report: ${r}`),i+=R(`Data: ${t}`),i+=s,process.stderr.write(i);}function O(e){switch(e){case "passed":return "passed";case "failed":return "failed";case "timedOut":return "timedout";case "skipped":return "skipped";case "interrupted":return "failed";default:return "failed"}}function me(e,t,r){let a=`${e}::${t}::${r}`;return crypto.createHash("sha256").update(a).digest("hex").substring(0,16)}function be(e){return e.length<=4?"":e[e.length-2]}function ve(e){let t=e.findIndex(r=>r.status==="passed");return t>0?`passed on retry ${t}`:null}function ye(e,t){let r=["e2e","api","unit"];for(let a of r)if(e.some(n=>n===`@${a}`||n===a))return a;for(let a of r)if(t.includes(`/${a}/`))return a;return "unknown"}var xe="__testrelic_api_config";function we(e){return JSON.stringify(e,(t,r)=>r instanceof RegExp?{__regexp:true,source:r.source,flags:r.flags}:r)}var L=class{constructor(t){this.rootDir="";this.startedAt="";this.testRunId="";this.collectedTests=[];this.config=V(t),this.apiConfig=G(t);}onBegin(t,r){try{this.rootDir=t.rootDir,this.startedAt=new Date().toISOString(),this.testRunId=this.config.testRunId??crypto.randomUUID();}catch{}}onTestBegin(t,r){try{t.annotations.push({type:xe,description:we(this.apiConfig)});}catch{}}onTestEnd(t,r){try{let a=r,n=t.outcome(),s;n==="flaky"?s="flaky":n==="skipped"?s="skipped":s=O(a.status);let o=a.startTime.toISOString(),i=new Date(a.startTime.getTime()+a.duration).toISOString(),l=t.tags?[...t.tags]:t.annotations.filter(x=>x.type==="tag").map(x=>x.description??""),u=[],d=null,f=null,p=null,c=a.attachments.filter(x=>x.name===core.ATTACHMENT_NAME&&x.body),w=!1;if(c.length>0)for(let x of c)try{let h=JSON.parse(x.body.toString());core.isTestRelicDataPayload(h)&&(u=u.concat(h.navigations),h.networkRequests.length>0&&(d=(d??[]).concat(h.networkRequests)),h.apiCalls.length>0&&(f=(f??[]).concat(h.apiCalls)),h.apiAssertions.length>0&&(p=(p??[]).concat(h.apiAssertions)),w=!0);}catch{process.stderr.write(`[testrelic] Warning: Corrupt attachment for test "${t.title}", falling back to annotations
|
|
1397
|
+
`);}if(!w){u=t.annotations.filter(b=>b.type==="lambdatest-navigation"&&b.description).map(b=>{try{return JSON.parse(b.description)}catch{return null}}).filter(b=>b!==null);let x=t.annotations.find(b=>b.type==="__testrelic_network_requests"&&b.description);if(x)try{d=JSON.parse(x.description);}catch{}let h=t.annotations.find(b=>b.type==="__testrelic_api_calls"&&b.description);if(h)try{f=JSON.parse(h.description);}catch{}let A=t.annotations.find(b=>b.type==="__testrelic_api_assertions"&&b.description);if(A)try{p=JSON.parse(A.description);}catch{}}u.length===0&&!d&&!f&&!p&&s!=="skipped"&&process.stderr.write(`[testrelic] Warning: No data found for test "${t.title}", data may be incomplete due to worker crash
|
|
1398
|
+
`);let k=null;if(s==="failed"||s==="flaky"){let h=(s==="flaky"?t.results.find(A=>A.status!=="passed")?.errors??[]:a.errors)[0];if(h){let A=Y(this.config.redactPatterns),b=h.location?.line??null,I=null;this.config.includeCodeSnippets&&b!==null&&h.location?.file&&(I=J(h.location.file,b,this.config.codeContextLines),I&&(I=A(I))),k={message:A(h.message??"Unknown error"),line:b,code:I,stack:this.config.includeStackTrace&&h.stack?A(h.stack):null};}}let m=t.titlePath().filter(Boolean),y=path.relative(this.rootDir||".",t.location.file),g=be(m),v=m.join(" > "),T=y,S=me(T,g,v),St=ye(l,T),At=n==="flaky",Nt=ve(t.results),_t=O(t.expectedStatus),qt=O(a.status),$=null;if(this.config.includeArtifacts&&s!=="skipped"&&a.attachments){let x=path.dirname(this.config.outputPath),h=m[m.length-1]??t.title;$=dt(a.attachments,h,a.retry,x);}this.collectedTests.push({titlePath:m,title:v,status:s,duration:a.duration,startedAt:o,completedAt:i,retryCount:t.results.length-1,retry:a.retry,tags:l,failure:k,specFile:y,navigations:u,testId:S,filePath:T,suiteName:g,testType:St,isFlaky:At,retryStatus:Nt,expectedStatus:_t,actualStatus:qt,artifacts:$,networkRequests:d,apiCalls:f,apiAssertions:p});}catch{}}onEnd(t){try{let r=new Date().toISOString(),a=new Date(this.startedAt).getTime(),s=new Date(r).getTime()-a,o=this.buildTimeline(),i=gt(this.collectedTests,o.length),l={schemaVersion:F,testRunId:this.testRunId,startedAt:this.startedAt,completedAt:r,totalDuration:s,summary:i,ci:Z(),metadata:this.config.metadata,timeline:o,shardRunIds:null};this.writeReport(l),st(l,this.config),ft(i,this.config.outputPath,this.config.htmlReportPath,this.config.quiet);}catch{}}printsToStdio(){return false}buildTimeline(){let t=this.collectedTests.map(r=>({titlePath:r.titlePath,title:r.title,status:r.status,duration:r.duration,startedAt:r.startedAt,completedAt:r.completedAt,retryCount:r.retryCount,retry:r.retry,tags:r.tags,failure:r.failure,specFile:r.specFile,navigations:r.navigations,apiCalls:r.apiCalls,apiAssertions:r.apiAssertions,testId:r.testId,filePath:r.filePath,suiteName:r.suiteName,testType:r.testType,isFlaky:r.isFlaky,retryStatus:r.retryStatus,expectedStatus:r.expectedStatus,actualStatus:r.actualStatus,artifacts:r.artifacts,networkRequests:r.networkRequests}));return ut(t,{navigationTypes:this.config.navigationTypes})}toTestResult(t){return {title:t.title,status:t.status,duration:t.duration,startedAt:t.startedAt,completedAt:t.completedAt,retryCount:t.retryCount,tags:t.tags,failure:t.failure,testId:t.testId,filePath:t.filePath,suiteName:t.suiteName,testType:t.testType,isFlaky:t.isFlaky,retryStatus:t.retryStatus,expectedStatus:t.expectedStatus,actualStatus:t.actualStatus,artifacts:t.artifacts,networkRequests:t.networkRequests,apiCalls:t.apiCalls,apiAssertions:t.apiAssertions}}writeReport(t){try{let r=JSON.stringify(t,null,2),a=this.config.outputPath,n=path.dirname(a);fs.mkdirSync(n,{recursive:!0});let s=a+".tmp";fs.writeFileSync(s,r,"utf-8"),fs.renameSync(s,a);}catch(r){process.stderr.write(`[testrelic] Failed to write report: ${r instanceof Error?r.message:String(r)}
|
|
1399
|
+
`);}}};var Se=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"];function Ae(e){let t=e.toLowerCase();return Se.some(r=>t.includes(r))}function mt(e,t){let r=new TextEncoder().encode(e);return r.length<=t?{text:e,truncated:false}:{text:new TextDecoder().decode(r.slice(0,t)),truncated:true}}var B=class{constructor(t,r){this.page=t;this.records=[];this.listeners=[];this.currentNetworkCounter=null;this.pendingRequests=new Map;this.capturedRequests=[];this.pendingBodyReads=[];this.requestIdCounter=0;this.requestCaptureCount=0;this.includeNetworkStats=r?.includeNetworkStats??true,this.origGoto=t.goto.bind(t),this.origGoBack=t.goBack.bind(t),this.origGoForward=t.goForward.bind(t),this.origReload=t.reload.bind(t),this.interceptMethods(),this.attachListeners();}async init(){await this.injectSPADetection();}async getCapturedRequests(){await Promise.allSettled(this.pendingBodyReads),this.pendingBodyReads=[];for(let[t,r]of this.pendingRequests)this.capturedRequests.push({url:r.url,method:r.method,resourceType:r.resourceType,statusCode:0,responseTimeMs:Date.now()-r.startTimeMs,startedAt:r.startedAt,requestHeaders:r.headers,requestBody:r.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:r.postDataTruncated,responseBodyTruncated:false,isBinary:false,error:"incomplete"}),this.pendingRequests.delete(t);return [...this.capturedRequests].sort((t,r)=>t.startedAt.localeCompare(r.startedAt))}async getData(){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}});let t=this.records.map(a=>({url:a.url,navigationType:a.navigationType,timestamp:a.timestamp,domContentLoadedAt:a.domContentLoadedAt,networkIdleAt:a.networkIdleAt,networkStats:a.networkStats})),r=this.includeNetworkStats?await this.getCapturedRequests():[];return {navigations:t,networkRequests:r}}async flushLegacyAnnotations(t){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}});for(let r of this.records){let a={url:r.url,navigationType:r.navigationType,timestamp:r.timestamp,domContentLoadedAt:r.domContentLoadedAt,networkIdleAt:r.networkIdleAt,networkStats:r.networkStats};t.annotations.push({type:"lambdatest-navigation",description:JSON.stringify(a)});}if(this.includeNetworkStats){let r=await this.getCapturedRequests();r.length>0&&t.annotations.push({type:"__testrelic_network_requests",description:JSON.stringify(r)});}}dispose(){this.page.goto=this.origGoto,this.page.goBack=this.origGoBack,this.page.goForward=this.origGoForward,this.page.reload=this.origReload;for(let{event:t,handler:r}of this.listeners)this.page.off(t,r);this.listeners=[],this.records=[],this.pendingRequests.clear(),this.capturedRequests=[],this.pendingBodyReads=[],this.requestCaptureCount=0;}getRecords(){return this.records}interceptMethods(){let t=this,r=this.page;r.goto=async function(a,n){return t.recordNavigation(a,"goto"),t.origGoto(a,n)},r.goBack=async function(a){let n=await t.origGoBack(a);return t.recordNavigation(r.url(),"back"),n},r.goForward=async function(a){let n=await t.origGoForward(a);return t.recordNavigation(r.url(),"forward"),n},r.reload=async function(a){return t.recordNavigation(r.url(),"refresh"),t.origReload(a)};}attachListeners(){let t=()=>{this.lastDomContentLoaded=new Date().toISOString(),this.records.length>0&&(this.records[this.records.length-1].domContentLoadedAt=this.lastDomContentLoaded);};this.page.on("domcontentloaded",t),this.listeners.push({event:"domcontentloaded",handler:t});let r=n=>{try{let s=n;if(typeof s.parentFrame=="function"&&s.parentFrame()!==null)return;let o=s.url(),i=this.records[this.records.length-1];if(i&&Date.now()-new Date(i.timestamp).getTime()<50&&i.url===o)return;this.recordNavigation(o,"navigation");}catch{}};this.page.on("framenavigated",r),this.listeners.push({event:"framenavigated",handler:r});let a=n=>{try{let s=n;if(s.type()!=="debug")return;let o=s.text();if(!o.startsWith("__testrelic_nav:"))return;let i=JSON.parse(o.slice(16));i.type&&i.url&&this.recordNavigation(i.url,i.type);}catch{}};if(this.page.on("console",a),this.listeners.push({event:"console",handler:a}),this.includeNetworkStats){let n=i=>{if(this.currentNetworkCounter&&this.currentNetworkCounter.totalRequests++,!(this.requestCaptureCount>=500)){this.requestCaptureCount++;try{let l=i,u=String(this.requestIdCounter++),d=l.postData()??null,f=!1;if(d!==null){let c=mt(d,10240);d=c.text,f=c.truncated;}let p={url:l.url(),method:l.method(),resourceType:this.mapResourceType(l.resourceType()),headers:l.headers(),postData:d,postDataTruncated:f,startedAt:new Date().toISOString(),startTimeMs:Date.now()};this.pendingRequests.set(u,p),i.__testrelic_id=u;}catch{}}};this.page.on("request",n),this.listeners.push({event:"request",handler:n});let s=i=>{try{let l=i;if(this.currentNetworkCounter){let m=l.status();m>=400&&(this.currentNetworkCounter.failedRequests++,this.currentNetworkCounter.failedRequestUrls.push(m+" "+l.url()));let y=l.headers()["content-length"];y&&(this.currentNetworkCounter.totalBytes+=parseInt(y,10)||0);let g=l.request().resourceType(),v=this.mapResourceType(g);this.currentNetworkCounter.byType[v]++;}let u=l.request().__testrelic_id;if(!u)return;let d=this.pendingRequests.get(u);if(!d)return;this.pendingRequests.delete(u);let f=Date.now()-d.startTimeMs,p=l.headers(),c=p["content-type"]??null,w=parseInt(p["content-length"]??"0",10)||0,C=c?!Ae(c):!1,k=(async()=>{let m=null,y=!1;if(!C)try{let T=(await l.body()).toString("utf-8"),S=mt(T,10240);m=S.text,y=S.truncated;}catch{}let g={url:d.url,method:d.method,resourceType:d.resourceType,statusCode:l.status(),responseTimeMs:f,startedAt:d.startedAt,requestHeaders:d.headers,requestBody:d.postData,responseBody:m,responseHeaders:p,contentType:c,responseSize:w,requestBodyTruncated:d.postDataTruncated,responseBodyTruncated:y,isBinary:C,error:null};this.capturedRequests.push(g);})();this.pendingBodyReads.push(k);}catch{}};this.page.on("response",s),this.listeners.push({event:"response",handler:s});let o=i=>{if(this.currentNetworkCounter){this.currentNetworkCounter.failedRequests++;try{let l=i;this.currentNetworkCounter.failedRequestUrls.push("ERR "+l.url());}catch{}}try{let l=i,u=l.__testrelic_id;if(!u)return;let d=this.pendingRequests.get(u);if(!d)return;this.pendingRequests.delete(u);let f={url:d.url,method:d.method,resourceType:d.resourceType,statusCode:0,responseTimeMs:Date.now()-d.startTimeMs,startedAt:d.startedAt,requestHeaders:d.headers,requestBody:d.postData,responseBody:null,responseHeaders:null,contentType:null,responseSize:0,requestBodyTruncated:d.postDataTruncated,responseBodyTruncated:!1,isBinary:!1,error:l.failure()?.errorText??"Unknown error"};this.capturedRequests.push(f);}catch{}};this.page.on("requestfailed",o),this.listeners.push({event:"requestfailed",handler:o});}}async injectSPADetection(){try{await this.page.addInitScript(()=>{let t=history.pushState.bind(history),r=history.replaceState.bind(history);history.pushState=function(...a){t(...a),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_route",url:location.href}));},history.replaceState=function(...a){r(...a),console.debug("__testrelic_nav:"+JSON.stringify({type:"spa_replace",url:location.href}));},window.addEventListener("popstate",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"popstate",url:location.href}));}),window.addEventListener("hashchange",()=>{console.debug("__testrelic_nav:"+JSON.stringify({type:"hash_change",url:location.href}));});});}catch{}}recordNavigation(t,r){this.includeNetworkStats&&this.currentNetworkCounter&&this.records.length>0&&(this.records[this.records.length-1].networkStats={totalRequests:this.currentNetworkCounter.totalRequests,failedRequests:this.currentNetworkCounter.failedRequests,failedRequestUrls:[...this.currentNetworkCounter.failedRequestUrls],totalBytes:this.currentNetworkCounter.totalBytes,byType:{...this.currentNetworkCounter.byType}}),this.records.push({url:t,navigationType:r,timestamp:new Date().toISOString()}),this.includeNetworkStats&&(this.currentNetworkCounter=this.createNetworkCounter());}createNetworkCounter(){return {totalRequests:0,failedRequests:0,failedRequestUrls:[],totalBytes:0,byType:{xhr:0,document:0,script:0,stylesheet:0,image:0,font:0,other:0}}}mapResourceType(t){switch(t){case "xhr":case "fetch":return "xhr";case "document":return "document";case "script":return "script";case "stylesheet":return "stylesheet";case "image":return "image";case "font":return "font";default:return "other"}}};var bt=Symbol.for("__testrelic_call_id"),Ne="__testrelic_api_assertions",_=new WeakMap,N=class{constructor(){this.assertions=[];this.currentCallId=null;}recordAssertion(t){this.assertions.push(t);}getAssertions(){return this.assertions}setCurrentCallId(t){this.currentCallId=t;}getCurrentCallId(){return this.currentCallId}getData(){return [...this.assertions]}flushLegacyAnnotations(t){this.assertions.length!==0&&t.annotations.push({type:Ne,description:JSON.stringify(this.assertions)});}dispose(){this.assertions=[],this.currentCallId=null;}};var vt="[REDACTED]";function z(e,t){if(e===null||t.length===0)return e;let r=new Set(t.map(n=>n.toLowerCase())),a={};for(let n of Object.keys(e))Object.hasOwn(e,n)&&(a[n]=r.has(n.toLowerCase())?vt:e[n]);return a}function E(e,t){if(e===null||t.length===0)return e;let r;try{r=JSON.parse(e);}catch{return e}if(typeof r!="object"||r===null)return e;let a=new Set(t),n=H(r,a);return JSON.stringify(n)}function H(e,t){if(Array.isArray(e))return e.map(r=>H(r,t));if(typeof e=="object"&&e!==null){let r={};for(let a of Object.keys(e)){if(!Object.hasOwn(e,a))continue;let n=e[a];t.has(a)?r[a]=vt:r[a]=H(n,t);}return r}return e}function xt(e,t,r){if(r.length>0){for(let a of r)if(yt(e,a))return false}if(t.length>0){for(let a of t)if(yt(e,a))return true;return false}return true}function yt(e,t){try{return t instanceof RegExp?t.test(e):_e(t).test(e)}catch{return console.warn(`[testrelic] Invalid URL filter pattern: ${String(t)}`),false}}function _e(e){let t="",r=0;for(;r<e.length;){let a=e[r];a==="*"&&e[r+1]==="*"?(t+=".*",r+=2,e[r]==="/"&&r++):a==="*"?(t+="[^/]*",r++):a==="?"?(t+="[^/]",r++):".+^${}()|[]\\".includes(a)?(t+="\\"+a,r++):(t+=a,r++);}return new RegExp(t)}var qe=["get","post","put","patch","delete","head","fetch"],Ie=["text/","application/json","application/xml","application/javascript","application/x-www-form-urlencoded","application/graphql"],Le="__testrelic_api_calls";function Be(e){let t=e.toLowerCase();return Ie.some(r=>t.includes(r))}function Ee(e){if(!e)return null;if(e.data!==void 0&&e.data!==null){let t=e.data;return typeof t=="string"?t:Buffer.isBuffer(t)?t.toString("base64"):JSON.stringify(t)}if(e.form!==void 0&&e.form!==null)return JSON.stringify(e.form);if(e.multipart!==void 0&&e.multipart!==null){let t=e.multipart,r={};for(let[a,n]of Object.entries(t))typeof n=="string"||typeof n=="number"||typeof n=="boolean"?r[a]=String(n):n&&typeof n=="object"&&"name"in n?r[a]=`[file: ${n.name}]`:r[a]="[binary]";return JSON.stringify(r)}return null}var D=class D{constructor(t,r,a){this.originals=new Map;this.capturedCalls=[];this.callCounter=0;this.disposed=false;this._lastCallId=null;this.primitiveCallIds=new Map;this.context=t,this.assertionTracker=r??null,this.apiConfig=a??D.DEFAULT_API_CONFIG;}get lastCallId(){return this._lastCallId}getCallIdForValue(t){return t!=null&&typeof t=="object"?_.get(t)??null:this.primitiveCallIds.get(t)??null}intercept(){for(let r of qe){let a=this.context[r].bind(this.context);this.originals.set(r,a),this.context[r]=this.createWrapper(r,a);}let t=this.context.dispose.bind(this.context);this.originals.set("dispose",t),this.context.dispose=async r=>(this.disposed=true,t(r));}getData(){return [...this.capturedCalls]}flushLegacyAnnotations(t){this.capturedCalls.length!==0&&t.annotations.push({type:Le,description:JSON.stringify(this.capturedCalls)});}dispose(){for(let[t,r]of this.originals)this.context[t]=r;this.originals.clear(),this.capturedCalls=[],this.callCounter=0,this._lastCallId=null,this.primitiveCallIds.clear();}get isDisposed(){return this.disposed}getCapturedCalls(){return this.capturedCalls}tagResponseMethods(t,r){let a=this,n=t.headers.bind(t);t.headers=function(){let c=n();return _.set(c,r),c};let s=t.headersArray.bind(t);t.headersArray=function(){let c=s();return _.set(c,r),c};let o=t.json.bind(t);t.json=async function(){let c=await o();return c!=null&&typeof c=="object"&&_.set(c,r),c};let i=t.status.bind(t);t.status=function(){let c=i();return a.primitiveCallIds.set(c,r),c};let l=t.statusText.bind(t);t.statusText=function(){let c=l();return a.primitiveCallIds.set(c,r),c};let u=t.ok.bind(t);t.ok=function(){let c=u();return a.primitiveCallIds.set(c,r),c};let d=t.text.bind(t);t.text=async function(){let c=await d();return a.primitiveCallIds.set(c,r),c};let f=t.body.bind(t);t.body=async function(){let c=await f();return _.set(c,r),c};}createWrapper(t,r){let a=this;return async function(s,o){if(!xt(s,a.apiConfig.apiIncludeUrls,a.apiConfig.apiExcludeUrls))return r(s,o);let i=`api-call-${a.callCounter++}`,l=new Date().toISOString(),u=t==="fetch"?(o?.method??"GET").toUpperCase():t.toUpperCase(),d=Ee(o),f=perf_hooks.performance.now();a._lastCallId=i,a.assertionTracker&&a.assertionTracker.setCurrentCallId(i);let p;try{p=await r(s,o);}catch(c){let w=perf_hooks.performance.now();try{let C=a.apiConfig.captureRequestBody?E(d,a.apiConfig.redactBodyFields):null,k={id:i,timestamp:l,method:u,url:s,requestHeaders:null,requestBody:C,responseStatusCode:null,responseStatusText:null,responseHeaders:null,responseBody:null,responseTimeMs:Math.round((w-f)*100)/100,isBinary:!1,error:c instanceof Error?c.message:String(c)};a.capturedCalls.push(k);}catch{}throw c}try{let c=perf_hooks.performance.now(),w=p.headers(),C=w["content-type"]??null,k=C?!Be(C):!1,m=null;a.apiConfig.captureRequestHeaders&&o?.headers&&(m=o.headers);let y=null;a.apiConfig.captureResponseHeaders&&(y=w);let g=a.apiConfig.captureRequestBody?d:null,v=null;if(a.apiConfig.captureResponseBody)try{k?v=(await p.body()).toString("base64"):v=await p.text();}catch{}m=z(m,a.apiConfig.redactHeaders),y=z(y,a.apiConfig.redactHeaders),g=E(g,a.apiConfig.redactBodyFields),v=E(v,a.apiConfig.redactBodyFields);let T={id:i,timestamp:l,method:u,url:p.url(),requestHeaders:m,requestBody:g,responseStatusCode:p.status(),responseStatusText:p.statusText(),responseHeaders:y,responseBody:v,responseTimeMs:Math.round((c-f)*100)/100,isBinary:k,error:null};a.capturedCalls.push(T);}catch{}try{p[bt]=i,a.tagResponseMethods(p,i);}catch{}return p}}};D.DEFAULT_API_CONFIG=Object.freeze({trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]});var q=D;var Fe="__testrelic_api_config",Me="__testrelic_config_trackApiCalls";function j(e){let t=e.annotations.find(a=>a.type===Fe&&a.description!==void 0);if(t)try{return JSON.parse(t.description,Pe)}catch{}let r=e.annotations.find(a=>a.type===Me&&a.description!==void 0);return r?{trackApiCalls:r.description!=="false",captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}:{trackApiCalls:true,captureRequestHeaders:true,captureResponseHeaders:true,captureRequestBody:true,captureResponseBody:true,captureAssertions:true,redactHeaders:["authorization","cookie","set-cookie","x-api-key"],redactBodyFields:["password","secret","token","apiKey","api_key"],apiIncludeUrls:[],apiExcludeUrls:[]}}function Pe(e,t){if(typeof t=="object"&&t!==null&&t.__regexp===true&&typeof t.source=="string"){let{source:r,flags:a}=t;return new RegExp(r,a)}return t}var Tt={page:async({page:e},t,r)=>{let a=new B(e);try{await a.init();}catch{}await t(e);try{let{navigations:n,networkRequests:s}=await a.getData(),o={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:n,networkRequests:s,apiCalls:[],apiAssertions:[]};await r.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(o)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{await a.flushLegacyAnnotations(r);}catch{}a.dispose();},request:async({request:e},t,r)=>{let a=j(r);if(!a.trackApiCalls){await t(e);return}let n=new N,s=new q(e,n,a);s.intercept(),await t(e);try{let o=s.getData(),i=a.captureAssertions?n.getData():[],l={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:o,apiAssertions:i};await r.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(l)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{s.flushLegacyAnnotations(r);}catch{}try{n.flushLegacyAnnotations(r);}catch{}s.dispose(),n.dispose();}};test.test.extend(Tt);var Ue={request:async({request:e},t,r)=>{let a=j(r);if(!a.trackApiCalls){await t(e);return}let n=new N,s=new q(e,n,a);s.intercept(),await t(e);try{let o=s.getData(),i=a.captureAssertions?n.getData():[],l={testRelicData:!0,version:core.PAYLOAD_VERSION,navigations:[],networkRequests:[],apiCalls:o,apiAssertions:i};await r.attach(core.ATTACHMENT_NAME,{body:Buffer.from(JSON.stringify(l)),contentType:core.ATTACHMENT_CONTENT_TYPE});}catch{}try{s.flushLegacyAnnotations(r);}catch{}try{n.flushLegacyAnnotations(r);}catch{}s.dispose(),n.dispose();}};var Rt=false;function ca(e,t,r="manual_record"){if(!e||!e.annotations){Rt||(Rt=true,process.stderr.write(`[testrelic] recordNavigation: reporter not active, navigation not recorded
|
|
1400
|
+
`));return}let a={url:t,navigationType:r,timestamp:new Date().toISOString()};e.annotations.push({type:"lambdatest-navigation",description:JSON.stringify(a)});}Object.defineProperty(exports,"ATTACHMENT_CONTENT_TYPE",{enumerable:true,get:function(){return core.ATTACHMENT_CONTENT_TYPE}});Object.defineProperty(exports,"ATTACHMENT_NAME",{enumerable:true,get:function(){return core.ATTACHMENT_NAME}});Object.defineProperty(exports,"PAYLOAD_VERSION",{enumerable:true,get:function(){return core.PAYLOAD_VERSION}});Object.defineProperty(exports,"isTestRelicDataPayload",{enumerable:true,get:function(){return core.isTestRelicDataPayload}});exports.SCHEMA_VERSION=F;exports.default=L;exports.recordNavigation=ca;exports.testRelicApiFixture=Ue;exports.testRelicFixture=Tt;//# sourceMappingURL=index.cjs.map
|
|
1401
1401
|
//# sourceMappingURL=index.cjs.map
|