skeptic-cli 0.2.0 → 1.0.0

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.
Files changed (79) hide show
  1. package/AGENTS.md +25 -53
  2. package/LICENSE +24 -0
  3. package/LICENSES.md +92 -3
  4. package/README.md +36 -52
  5. package/agent-skills/skeptic/SKILL.md +151 -33
  6. package/dist/adb-DUGGW3FV.mjs +2 -0
  7. package/dist/adb-driver-TBOCCKEO.mjs +3 -0
  8. package/dist/adb-session-AVVXL3QQ.mjs +2 -0
  9. package/dist/add-G7JFXU4S.mjs +67 -0
  10. package/dist/audit-ID2BSVYC.mjs +7 -0
  11. package/dist/auto-spawn-4TO4DBO6.mjs +2 -0
  12. package/dist/browser-verbs-U54BZACP.mjs +21 -0
  13. package/dist/browsers-install-F2ZWEBOX.mjs +3 -0
  14. package/dist/chokidar-KB6GLGX4.mjs +7 -0
  15. package/dist/chunk-2N64R5DC.mjs +457 -0
  16. package/dist/chunk-2VSGDT7T.mjs +7 -0
  17. package/dist/chunk-2YKSIUIN.mjs +3 -0
  18. package/dist/chunk-2ZORFJJP.mjs +11 -0
  19. package/dist/chunk-42J77CYA.mjs +3 -0
  20. package/dist/chunk-6TLKI7UN.mjs +4 -0
  21. package/dist/chunk-6U6H22OR.mjs +3 -0
  22. package/dist/chunk-7BFRKEFV.mjs +160 -0
  23. package/dist/chunk-7ZUWKIDM.mjs +3 -0
  24. package/dist/chunk-AH75LR2T.mjs +3 -0
  25. package/dist/chunk-B26AZRXU.mjs +41 -0
  26. package/dist/chunk-BIGNULF6.mjs +12 -0
  27. package/dist/chunk-COVGJJ47.mjs +3 -0
  28. package/dist/chunk-CWNYWHJ2.mjs +143 -0
  29. package/dist/chunk-EU3OXJX4.mjs +3 -0
  30. package/dist/chunk-EYVJTUBL.mjs +3 -0
  31. package/dist/chunk-G22LGRZ4.mjs +4 -0
  32. package/dist/chunk-I4JX25Y5.mjs +13 -0
  33. package/dist/chunk-IXBYLSGB.mjs +5 -0
  34. package/dist/chunk-IYLF56WL.mjs +3 -0
  35. package/dist/chunk-K65JNLTT.mjs +3 -0
  36. package/dist/chunk-LPJF33QP.mjs +3 -0
  37. package/dist/chunk-MHNEFL35.mjs +3 -0
  38. package/dist/chunk-N3533BCE.mjs +3 -0
  39. package/dist/chunk-NXTEMSUR.mjs +4 -0
  40. package/dist/chunk-OHVNABCL.mjs +10 -0
  41. package/dist/chunk-QICYK6XT.mjs +10 -0
  42. package/dist/chunk-RU7M6UGM.mjs +5 -0
  43. package/dist/chunk-S3M2RTHJ.mjs +7 -0
  44. package/dist/chunk-U3KRIAEU.mjs +3 -0
  45. package/dist/chunk-WBPZGXOC.mjs +8 -0
  46. package/dist/chunk-YB25SMQ2.mjs +141 -0
  47. package/dist/chunk-ZN6MI2TU.mjs +4 -0
  48. package/dist/client-UR65IKYX.mjs +2 -0
  49. package/dist/comment-F734YE5S.mjs +6 -0
  50. package/dist/cookies-X7W5U3VE.mjs +3 -0
  51. package/dist/daemon-M2J3L6JW.mjs +7 -0
  52. package/dist/device-fixture-MJSDIP75.mjs +2 -0
  53. package/dist/devices-NG4P5UPS.mjs +4 -0
  54. package/dist/devtools-N5AYAR54.mjs +12 -0
  55. package/dist/doctor-WRKNAK3W.mjs +4 -0
  56. package/dist/extractor-Y477MBN6.mjs +2 -0
  57. package/dist/html-reporter-7QHIRHEY.mjs +2 -0
  58. package/dist/index.d.ts +87 -120
  59. package/dist/index.mjs +30 -1740
  60. package/dist/init-4PXSHPNW.mjs +15 -0
  61. package/dist/ink-reporter-4EN7CRMK.mjs +3 -0
  62. package/dist/inspect-3XFCCSUL.mjs +19 -0
  63. package/dist/ios-tools-WK66CQ7Q.mjs +2 -0
  64. package/dist/json-reporter-SXWPAXRY.mjs +2 -0
  65. package/dist/junit-reporter-5AT3OFWV.mjs +12 -0
  66. package/dist/mail-GTOZFXJ5.mjs +14 -0
  67. package/dist/observe-MHEV7OVP.mjs +3 -0
  68. package/dist/render-MHOBDOSP.mjs +383 -0
  69. package/dist/run-GW3X5ANC.mjs +2 -0
  70. package/dist/scaffold-6ZF6K6Y5.mjs +38 -0
  71. package/dist/screenshot-GUJSIRQB.mjs +2 -0
  72. package/dist/session-daemon-cmd-23UUK6TD.mjs +4 -0
  73. package/dist/simctl-driver-PNUN7W7G.mjs +5 -0
  74. package/dist/skeptic.mjs +3 -1749
  75. package/dist/slack-reporter-EEFO66V6.mjs +8 -0
  76. package/dist/watch-A7ZLUYR2.mjs +3 -0
  77. package/dist/webhook-reporter-BXJGZS2I.mjs +3 -0
  78. package/dist/worker.mjs +3 -724
  79. package/package.json +13 -11
@@ -0,0 +1,15 @@
1
+ import {createRequire}from'node:module';import {a as a$2}from'./chunk-7ZUWKIDM.mjs';import {d}from'./chunk-ZN6MI2TU.mjs';import {a,c,d as d$1}from'./chunk-MHNEFL35.mjs';import {a as a$1}from'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';import*as t from'fs';import*as r from'path';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ var m=".skeptic",$=`*
4
+ !.gitignore
5
+ `,x=`{
6
+ "type": "module"
7
+ }
8
+ `;async function T(s=process.cwd()){let e=r.resolve(s);d.info(`Initializing ${a} project in ${a$1.cyan(e)}`);let c$1=r.join(e,"tests");S(c$1),d.success(`Created ${a$1.dim("tests/")}`),P(e),R(e),C(e),E(c$1);let o=r.join(e,c);t.existsSync(o)?d.warn(`${c} already exists, skipping`):(t.writeFileSync(o,a$2("skeptic.config.yaml")),d.success(`Created ${a$1.dim(c)}`));let p=r.join(c$1,"example.spec.ts");t.existsSync(p)?d.warn("Example test already exists, skipping"):(t.writeFileSync(p,a$2("example.spec.ts")),d.success(`Created ${a$1.dim("tests/example.spec.ts")}`));let l=r.join(e,"tsconfig.json");t.existsSync(l)?d.warn("tsconfig.json already exists, skipping"):(t.writeFileSync(l,a$2("tsconfig.json")),d.success(`Created ${a$1.dim("tsconfig.json")}`)),d.info("Installing Playwright browsers...");try{let{runBrowsersInstall:g}=await import('./browsers-install-F2ZWEBOX.mjs');await g(["chromium"],{withDeps:!0}),d.success("Playwright Chromium installed");}catch{d.warn(`Failed to install Playwright browsers automatically.
9
+ Run manually: ${a$1.cyan("skeptic browsers install --with-deps chromium")}`);}console.log(),console.log(a$1.bold(" Next steps:"));let a$3=1;console.log(a$1.dim(` ${a$3}.`)+` Run ${a$1.cyan(j(e).join(" "))}`),a$3+=1,console.log(a$1.dim(` ${a$3}.`)+` Edit ${a$1.cyan(c)} with your base URL`),a$3+=1,console.log(a$1.dim(` ${a$3}.`)+` Write tests in ${a$1.cyan("tests/*.spec.ts")}`),a$3+=1,console.log(a$1.dim(` ${a$3}.`)+` Run ${a$1.cyan("skeptic run")} to execute`),console.log();}function j(s){return t.existsSync(r.join(s,"pnpm-lock.yaml"))?["pnpm","install"]:t.existsSync(r.join(s,"yarn.lock"))?["yarn","install"]:t.existsSync(r.join(s,"bun.lock"))||t.existsSync(r.join(s,"bun.lockb"))?["bun","install"]:["npm","install"]}function S(s){t.existsSync(s)||t.mkdirSync(s,{recursive:true});}function C(s){let e=r.join(s,"package.json"),c="^1.0.0";if(!t.existsSync(e)){let g={name:r.basename(s).replace(/[^a-zA-Z0-9._-]/g,"-")||"skeptic-project",private:true,type:"module",scripts:{"test:e2e":"skeptic run"},devDependencies:{"skeptic-cli":c}};t.writeFileSync(e,`${JSON.stringify(g,null,2)}
10
+ `,"utf-8"),d.success(`Created ${a$1.dim("package.json")}`);return}let o;try{o=JSON.parse(t.readFileSync(e,"utf-8"));}catch{d.warn("package.json exists but could not be parsed, skipping dependency/script update");return}let p=false;o.scripts??={},o.scripts["test:e2e"]||(o.scripts["test:e2e"]="skeptic run",p=true),o.dependencies?.["skeptic-cli"]!==void 0||o.devDependencies?.["skeptic-cli"]!==void 0||(o.devDependencies??={},o.devDependencies["skeptic-cli"]=c,p=true),p?(t.writeFileSync(e,`${JSON.stringify(o,null,2)}
11
+ `,"utf-8"),d.success(`Updated ${a$1.dim("package.json")} for skeptic`)):d.warn("package.json already has skeptic script/dependency, skipping");}function E(s){let e=r.join(s,"package.json");if(t.existsSync(e)){d.warn("tests/package.json already exists, skipping");return}t.writeFileSync(e,x,"utf-8"),d.success(`Created ${a$1.dim("tests/package.json")}`);}function P(s){let e=r.join(s,m);S(e);let c=r.join(e,".gitignore");if(t.existsSync(c)){d.warn(`${m}/.gitignore already exists, skipping`);return}t.writeFileSync(c,$,"utf-8"),d.success(`Created ${a$1.dim(`${m}/.gitignore`)}`);}function R(s){let e=r.join(s,".gitignore"),c=_(d$1),o=[m+"/",c],p=t.existsSync(e),l=p?t.readFileSync(e,"utf-8"):"",a=I(l),g=o.filter(w=>!a.has(y(w)));if(g.length===0){d.warn(".gitignore already ignores skeptic artifacts, skipping");return}let f=[];l.length>0&&!l.endsWith(`
12
+ `)&&f.push(""),l.trim().length>0&&f.push(""),f.push("# Skeptic artifacts",...g),t.appendFileSync(e,`${f.join(`
13
+ `)}
14
+ `,"utf-8"),d.success(p?`Updated ${a$1.dim(".gitignore")} for skeptic artifacts`:`Created ${a$1.dim(".gitignore")}`);}function I(s){let e=new Set;for(let c of s.split(/\r?\n/)){let o=y(c);o.length>0&&e.add(o);}return e}function y(s){let c=s.replace(/\s+#.*$/,"").trim();return c.length===0||c.startsWith("#")?"":c.replace(/^\.\//,"").replace(/^\/+/,"").replace(/\/+$/,"")}function _(s){let e=y(s.replaceAll(r.sep,"/"));return e.endsWith("/")?e:`${e}/`}
15
+ export{T as runInit};
@@ -0,0 +1,3 @@
1
+ import {createRequire}from'node:module';import'./chunk-2YKSIUIN.mjs';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ var o=()=>Date.now(),d=n=>`${n.file}#${n.testIndex??n.name}`,f=n=>n==="passed"?"passed":n==="failed"?"failed":"error",g=n=>{switch(n){case "passed":return "passed";case "failed":return "failed";case "error":return "error";case "skipped":return "skipped"}},m=n=>({index:n,command:"",args:void 0,phase:"pending",durationMs:0}),h=(n,e)=>(n.command=e.command,n.args=e.args,n.phase=g(e.status),n.durationMs=e.duration_ms,n.completedAt=o(),n.error=e.error,n.screenshot=e.screenshot,n.baselinePath=e.baselinePath,n.currentPath=e.currentPath,n.diffPath=e.diffPath,n.warnings=e.warnings,n.diagnostics=e.diagnostics,n),p=class{snapshot={version:0,phase:"idle",startedAt:o(),tests:[],summary:null,focusedKey:null};testsByKey=new Map;listeners=new Set;getSnapshot=()=>this.snapshot;subscribe=e=>(this.listeners.add(e),()=>{this.listeners.delete(e);});runStart(e){this.testsByKey.clear();let s=o(),t=e.map((r,i)=>{let a=r.testIndex??i,u={key:d({...r,testIndex:a}),name:r.name,file:r.file,testIndex:a,phase:"queued",steps:Array.from({length:r.stepCount},(S,l)=>m(l)),stepCount:r.stepCount,activeStepIndex:-1,durationMs:0};return this.testsByKey.set(u.key,u),u});this.publish({phase:"running",startedAt:s,completedAt:void 0,tests:t,summary:null,focusedKey:t[0]?.key??null});}testStart(e){let s=this.ensureTest(e);s.phase="running",s.startedAt=o(),this.publish({focusedKey:s.key});}stepStart(e,s,t,r){let i=this.ensureTest(e);i.phase="running",i.stepCount=Math.max(i.stepCount,r,t+1);let a=this.ensureStep(i,t);a.command=s.command,a.args=s.args,a.phase="running",a.startedAt=o(),a.completedAt=void 0,a.error=void 0,i.activeStepIndex=t,this.publish({focusedKey:i.key});}stepComplete(e,s,t,r){let i=this.ensureTest(e);i.stepCount=Math.max(i.stepCount,r,t+1),h(this.ensureStep(i,t),s),this.publish();}testComplete(e,s){let t=this.ensureTest({...s,name:e.name,file:e.file,testIndex:e.testIndex??s.testIndex});t.phase=f(e.status),t.durationMs=e.duration_ms,t.completedAt=o(),t.artifacts=e.artifacts,t.metrics=e.metrics,t.shardId=e.shardId,t.stepCount=Math.max(t.stepCount,e.steps.length);for(let r=0;r<e.steps.length;r++){let i=e.steps[r];i&&h(this.ensureStep(t,r),i);}this.publish();}runComplete(e){this.publish({phase:"complete",completedAt:o(),summary:e,focusedKey:this.snapshot.focusedKey??this.snapshot.tests[0]?.key??null});}ensureTest(e){let s=d(e),t=this.testsByKey.get(s);if(t)return t.name=e.name,t.file=e.file,t.testIndex=e.testIndex,t;let r={key:s,name:e.name,file:e.file,testIndex:e.testIndex,phase:"queued",steps:[],stepCount:0,activeStepIndex:-1,durationMs:0};return this.testsByKey.set(s,r),this.snapshot.tests.push(r),r}ensureStep(e,s){for(;e.steps.length<=s;)e.steps.push(m(e.steps.length));return e.steps[s]}publish(e={}){this.snapshot={...this.snapshot,...e,version:this.snapshot.version+1};for(let s of this.listeners)s();}};var c=class{store=new p;getSnapshot=()=>this.store.getSnapshot();subscribe=e=>this.store.subscribe(e);onRunStart(e){this.store.runStart(e.tests);}onTestStart(e){this.store.testStart(e);}onStepStart(e,s,t,r){this.store.stepStart(r,e,s,t);}onStepComplete(e,s,t,r){this.store.stepComplete(r,e,s,t);}onTestComplete(e,s){this.store.testComplete(e,s);}onRunComplete(e){this.store.runComplete(e);}};export{c as InkReporter};
@@ -0,0 +1,19 @@
1
+ import {createRequire}from'node:module';import {a as a$1,c as c$1}from'./chunk-2ZORFJJP.mjs';export{a as buildSelectorHint}from'./chunk-2ZORFJJP.mjs';import {b}from'./chunk-NXTEMSUR.mjs';import {b as b$1}from'./chunk-OHVNABCL.mjs';import {c}from'./chunk-6U6H22OR.mjs';import'./chunk-7BFRKEFV.mjs';import'./chunk-N3533BCE.mjs';import {a}from'./chunk-IYLF56WL.mjs';import {d}from'./chunk-ZN6MI2TU.mjs';import'./chunk-MHNEFL35.mjs';import'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';import {setTimeout}from'timers/promises';import {resolve}from'path';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ var P=0,D=1e3,Y=async(n,t)=>{let s=H(t.wait),i=await a(),{prewarmDaemonIfNeeded:o}=await import('./auto-spawn-4TO4DBO6.mjs'),e=await o(process.argv,{engine:"chromium",headed:t.headed===true,cliVersion:"1.0.0",noDaemon:t.daemon===false||t.connect!==void 0}),r=null,a$1=null,c=null,w=t.daemon===false||!t.connect&&!e,R=!t.connect&&w,d=null;try{if(t.connect){let f=await W(t.connect);r=await i.chromium.connectOverCDP(f),a$1=r.contexts()[0]??await r.newContext(),c=a$1.pages()[0]??await a$1.newPage();}else if(w){r=await i.chromium.launch({headless:!t.headed});let f=I(t);a$1=await r.newContext(f),c=await a$1.newPage();}else {let{connectDaemon:f}=await import('./client-UR65IKYX.mjs'),u=await f({engine:"chromium",headed:t.headed===!0,cliVersion:"1.0.0"});r=u.browser,d=u.disconnect;let m=I(t);a$1=await r.newContext(m),c=await a$1.newPage();}await c.goto(n,{waitUntil:"domcontentloaded"}),await Promise.race([c.waitForLoadState("networkidle").catch(()=>{}),setTimeout(D)]),s>0&&await setTimeout(s);let k=new b(c,n),E={interactive:t.interactive??!1,compact:t.compact??!1,selector:t.selector,includeCursorInteractive:!0,viewportAware:!1},b$2=await b$1(c,k,E),p,g;if(t.annotated){let f=resolve(t.annotateOutput??`./skeptic-inspect-${Date.now()}.png`),{captureAnnotatedScreenshot:u}=await import('./screenshot-GUJSIRQB.mjs'),m=await u(c,f,{fullPage:!1,scope:t.selector??"body"});p=m.annotations,g=m.path;}t.json?T(n,b$2,t,p,g):N(b$2,t,p,g);}finally{try{d?(await a$1?.close().catch(()=>{}),await d()):R?await r?.close():await c?.close();}catch{}}},H=n=>{if(!n)return P;let t=Number.parseInt(n,10);return !Number.isFinite(t)||t<0?P:t},I=n=>{let t={};if(n.device){let s=c(n.device);s?(t.viewport={width:s.width,height:s.height},t.deviceScaleFactor=s.dpr,s.userAgent&&(t.userAgent=s.userAgent)):d.warn(`[inspect] unknown device profile "${n.device}" \u2014 using browser defaults`);}return t};var C=n=>{if(n.kind!=="aria")return;let t=n.name?`, { name: ${JSON.stringify(n.name)}, exact: true }`:"",s=n.nth>0?`.nth(${n.nth})`:"";return `page.getByRole(${JSON.stringify(n.role)}${t})${s}`},N=(n,t,s,i)=>{if(process.stdout.write(n.yaml),n.yaml.endsWith(`
4
+ `)||process.stdout.write(`
5
+ `),n.refs.size>0){let o=new Set([...n.yaml.matchAll(/\[ref=(e\d+)\]/g)].map(e=>e[1]));process.stdout.write(`
6
+ `);for(let e of n.refs.values()){if(!o.has(e.ref))continue;let r=a$1(e);if(process.stdout.write(` ${e.ref} selectorHint: ${r}
7
+ `),e.href&&process.stdout.write(` ${e.ref} /url: ${e.href}
8
+ `),t.withPlaywrightHints){let a=C(e);a&&process.stdout.write(` ${e.ref} playwrightHint: ${a}
9
+ `);}}}if(s&&s.length>0){process.stdout.write(`
10
+ Annotations:
11
+ `);for(let o of s){let e=n.refs.get(o.ref),r=e&&e.name&&e.name.length>0?` "${e.name}"`:' ""',a=e?.href?` /url: ${e.href}`:"";process.stdout.write(` [${o.label}] @${o.ref} ${o.role}${r}${a}
12
+ `);}i&&process.stdout.write(`
13
+ Annotated PNG: ${i}
14
+ `);}process.stdout.write(`
15
+ Stats: ${c$1(n.stats.lines)} lines, ${c$1(n.stats.characters)} chars, ~${c$1(n.stats.estimatedTokens)} tokens; ${c$1(n.stats.renderedRefs)} refs rendered / ${c$1(n.stats.totalRefs)} captured (${c$1(n.stats.ariaRefs)} ARIA, ${c$1(n.stats.cursorInteractiveRefs)} cursor-interactive), ${c$1(n.stats.interactiveRefs)} interactive.
16
+ Stable artifact: copy a selectorHint into your test \u2014 refs are NOT portable across inspect calls. Inside a test, use @eN only after a snapshot(page) call in the same run.
17
+ `);},T=(n,t,s,i,o)=>{let e={url:n,yaml:t.yaml,refs:[...t.refs.values()].filter(r=>t.yaml.includes(`[ref=${r.ref}]`)).map(r=>{let a={ref:r.ref,kind:r.kind,role:r.role,name:r.name,nth:r.nth,selectorHint:a$1(r)};if(r.href&&(a.href=r.href),s.withPlaywrightHints){let c=C(r);c&&(a.playwrightHint=c);}return a}),stats:t.stats,summary:{total:t.stats.totalRefs,aria:t.stats.ariaRefs,cursorInteractive:t.stats.cursorInteractiveRefs,rendered:t.stats.renderedRefs,interactive:t.stats.interactiveRefs}};i&&i.length>0&&(e.annotations=i),o&&(e.annotatedPath=o),process.stdout.write(`${JSON.stringify(e,null,2)}
18
+ `);},W=async n=>{let t=n.trim();if(t.startsWith("ws://")||t.startsWith("wss://"))return t;let{host:s,port:i}=U(t),o=e=>e.includes(":")&&!e.startsWith("[")?`[${e}]`:e;try{let e=await fetch(`http://${o(s)}:${i}/json/version`,{signal:AbortSignal.timeout(2e3)});if(e.ok){let r=await e.json();if(r.webSocketDebuggerUrl)return A(r.webSocketDebuggerUrl,s,i)}}catch{}try{let e=await fetch(`http://${o(s)}:${i}/json/list`,{signal:AbortSignal.timeout(2e3)});if(e.ok){let r=await e.json(),a=r.find(c=>c.type==="browser")??r[0];if(a?.webSocketDebuggerUrl)return A(a.webSocketDebuggerUrl,s,i)}}catch{}return `ws://${o(s)}:${i}/devtools/browser`},U=n=>{let t=n;t.startsWith("http://")&&(t=t.slice(7)),t.startsWith("https://")&&(t=t.slice(8)),t.startsWith(":")&&(t=`127.0.0.1${t}`);let s=t.indexOf("/");s>=0&&(t=t.slice(0,s));let i=t,o=9222;if(t.startsWith("[")){let e=t.indexOf("]");if(e>0){i=t.slice(1,e);let r=t.slice(e+1);r.startsWith(":")&&(o=Number(r.slice(1))||9222);}}else {let e=t.lastIndexOf(":");e>0&&(i=t.slice(0,e),o=Number(t.slice(e+1))||9222);}return {host:i,port:o}},A=(n,t,s)=>{try{let i=new URL(n);return i.hostname=t,i.port=String(s),i.toString()}catch{return n}};
19
+ export{W as discoverCdpUrl,H as parseWait,Y as runInspect};
@@ -0,0 +1,2 @@
1
+ import {createRequire}from'node:module';export{g as assertIosSimReady,e as axeAvailable,b as createIosTools,d as findAxeBinary,f as isIosSimAvailable,c as listBootedSimulators,a as resolveDeveloperDir}from'./chunk-LPJF33QP.mjs';import'./chunk-2YKSIUIN.mjs';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
@@ -0,0 +1,2 @@
1
+ import {createRequire}from'node:module';export{a as JsonReporter}from'./chunk-42J77CYA.mjs';import'./chunk-ZN6MI2TU.mjs';import'./chunk-MHNEFL35.mjs';import'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
@@ -0,0 +1,12 @@
1
+ import {createRequire}from'node:module';import {a}from'./chunk-EYVJTUBL.mjs';import {d}from'./chunk-ZN6MI2TU.mjs';import {a as a$1}from'./chunk-MHNEFL35.mjs';import'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';import*as l from'fs';import*as T from'path';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ var g=class{outputDir;silent;constructor(n,r={}){this.outputDir=n,this.silent=r.silent??false;}onTestStart(n){}onStepComplete(n,r,o,a){}onTestComplete(n,r){}onRunComplete(n){l.mkdirSync(this.outputDir,{recursive:true});let r=T.join(this.outputDir,"junit.xml"),o=(n.duration_ms/1e3).toFixed(3),a=n.tests.map(s=>k(s,n.tests)),u=a.reduce((s,m)=>s+m.tests,0),p=a.reduce((s,m)=>s+m.failures,0),c=a.reduce((s,m)=>s+m.skipped,0),e=['<?xml version="1.0" encoding="UTF-8"?>',`<testsuites name="${i(a$1)}" tests="${u}" failures="${p}" skipped="${c}" time="${o}">`,a.map(s=>s.xml).join(`
4
+ `),"</testsuites>"].join(`
5
+ `);l.writeFileSync(r,e,"utf-8"),this.silent||d.info(`JUnit report written to ${r}`);}};function k(t,n){let r=(t.duration_ms/1e3).toFixed(3),o=a(t,n);if(t.skipped&&t.steps.length===0)return {xml:` <testsuite name="${i(o)}" tests="1" failures="0" skipped="1" time="${r}">
6
+ <testcase classname="${i(o)}" name="${i(t.name)}" time="${r}"><skipped /></testcase>
7
+ </testsuite>`,tests:1,failures:0,skipped:1};let a$1=t.steps.filter(e=>e.status==="failed"||e.status==="error").length,u=t.steps.filter(e=>e.status==="skipped").length,p=t.steps.map(e=>{let s=(e.duration_ms/1e3).toFixed(3);if(e.status==="passed")return ` <testcase classname="${i(o)}" name="${i(e.command)}" time="${s}" />`;if(e.status==="skipped")return ` <testcase classname="${i(o)}" name="${i(e.command)}" time="${s}"><skipped /></testcase>`;let m=e.error?`
8
+ <failure message="${i(e.error)}">${i(e.error)}</failure>
9
+ `:"";return ` <testcase classname="${i(o)}" name="${i(e.command)}" time="${s}">${m}</testcase>`}).join(`
10
+ `);return {xml:` <testsuite name="${i(o)}" tests="${t.steps.length}" failures="${a$1}" skipped="${u}" time="${r}">
11
+ ${p}
12
+ </testsuite>`,tests:t.steps.length,failures:a$1,skipped:u}}function i(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}export{g as JUnitReporter};
@@ -0,0 +1,14 @@
1
+ import {createRequire}from'node:module';import {d}from'./chunk-ZN6MI2TU.mjs';import'./chunk-MHNEFL35.mjs';import'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';import*as S from'net';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ var w=s=>{let a=x(s),o=/(?:one[\s-]?time\s+(?:code|password)|verification\s+code|security\s+code|login\s+code|access\s+code|\bOTP\b|\bPIN\b|\bcode\b|passcode)\b[^\dA-Z]{0,24}([A-Z0-9]{4,8})/i.exec(a);if(o&&h(o[1]))return o[1].toUpperCase();let i=a.match(/(?<![A-Za-z0-9])(\d{4,8})(?![A-Za-z0-9])/g);if(i&&i.length>0)return i[0];let e=a.match(/(?<![A-Za-z0-9])([A-Z0-9]{6,8})(?![A-Za-z0-9])/g);if(e){let p=e.find(h);if(p)return p}return null},h=s=>/\d/.test(s),x=s=>s.replace(/<style[\s\S]*?<\/style>/gi," ").replace(/<script[\s\S]*?<\/script>/gi," ").replace(/<[^>]+>/g," ").replace(/&nbsp;/gi," ").replace(/&amp;/gi,"&").replace(/\s+/g," ");var y=async(s=0)=>{let a=[],o=[],i=t=>{a.push(t);for(let r=o.length-1;r>=0;r--)o[r].match(t)&&(o[r].resolve(t),o.splice(r,1));},e=S.createServer(t=>{t.setEncoding("utf8");let r="",m=false,g=[],d={from:"",to:[]},c=f=>{t.write(`${f}\r
4
+ `);};c("220 skeptic-smtp-sink ready"),t.on("data",f=>{r+=f;let u;for(;(u=r.indexOf(`
5
+ `))>=0;){let n=r.slice(0,u).replace(/\r$/,"");if(r=r.slice(u+1),m){n==="."?(m=false,i(M(d.from,d.to,g.join(`
6
+ `))),g=[],c("250 OK: queued")):g.push(n.startsWith("..")?n.slice(1):n);continue}let l=n.slice(0,4).toUpperCase();l==="HELO"||l==="EHLO"?c("250 OK"):l==="MAIL"?(d.from=C(n),c("250 OK")):l==="RCPT"?(d.to.push(C(n)),c("250 OK")):l==="DATA"?(m=true,c("354 End data with <CR><LF>.<CR><LF>")):l==="RSET"?(d.from="",d.to.length=0,c("250 OK")):l==="QUIT"?(c("221 Bye"),t.end()):c("250 OK");}}),t.on("error",()=>{});});return await new Promise((t,r)=>{e.once("error",r),e.listen(s,"127.0.0.1",()=>{e.removeListener("error",r),t();});}),{port:e.address().port,messages:()=>a.slice(),waitFor:({to:t,timeoutMs:r})=>new Promise((m,g)=>{let d=n=>!t||n.to.some(l=>l.toLowerCase().includes(t.toLowerCase())),c=a.find(d);if(c){m(c);return}let f=setTimeout(()=>{let n=o.findIndex(l=>l.resolve===u);n>=0&&o.splice(n,1),g(new Error(`no matching email${t?` to "${t}"`:""} within ${r}ms`));},r),u=n=>{clearTimeout(f),m(n);};o.push({match:d,resolve:u});}),close:()=>new Promise(t=>e.close(()=>t()))}},C=s=>/<([^>]*)>/.exec(s)?.[1]??s.split(":").slice(1).join(":").trim(),M=(s,a,o)=>{let i=o.search(/\r?\n\r?\n/),e=i>=0?o.slice(0,i):o,p=i>=0?o.slice(i).trim():"",t=r=>new RegExp(`^${r}:\\s*(.*)$`,"im").exec(e)?.[1]?.trim()??"";return {from:s||t("From"),to:a.length?a:t("To").split(",").map(r=>r.trim()).filter(Boolean),subject:t("Subject"),body:p,otp:w(`${t("Subject")}
7
+ ${p}`),receivedAt:Date.now()}};var j=async s=>{let a=s.port??2525,o=s.timeout??6e4,i;try{i=await y(a);}catch(e){d.error(`mail: could not start SMTP sink on port ${a}: ${e instanceof Error?e.message:String(e)}`),process.exitCode=1;return}process.stderr.write(`[skeptic] SMTP sink listening on 127.0.0.1:${i.port} \u2014 point the app's SMTP here, then trigger the email.
8
+ `);try{let e=await i.waitFor({...s.to?{to:s.to}:{},timeoutMs:o});s.json?process.stdout.write(`${JSON.stringify({success:!0,data:{port:i.port,from:e.from,to:e.to,subject:e.subject,otp:e.otp,body:e.body}})}
9
+ `):e.otp?process.stdout.write(`${e.otp}
10
+ `):(process.stdout.write(`(no code found)
11
+ Subject: ${e.subject}
12
+ ${e.body}
13
+ `),process.exitCode=1);}catch(e){let p=e instanceof Error?e.message:String(e);s.json?process.stdout.write(`${JSON.stringify({success:false,error:p})}
14
+ `):d.error(`mail: ${p}`),process.exitCode=1;}finally{await i.close();}};export{j as runMail};
@@ -0,0 +1,3 @@
1
+ import {createRequire}from'node:module';import {b,a}from'./chunk-WBPZGXOC.mjs';import {a as a$1}from'./chunk-42J77CYA.mjs';import {a as a$2}from'./chunk-YB25SMQ2.mjs';import'./chunk-EYVJTUBL.mjs';import'./chunk-EU3OXJX4.mjs';import {d}from'./chunk-CWNYWHJ2.mjs';import {d as d$3,b as b$2,a as a$8,c as c$2}from'./chunk-2N64R5DC.mjs';import'./chunk-6TLKI7UN.mjs';import {a as a$3,b as b$3}from'./chunk-NXTEMSUR.mjs';import'./chunk-7ZUWKIDM.mjs';import {b as b$4,a as a$9}from'./chunk-U3KRIAEU.mjs';import {b as b$1}from'./chunk-OHVNABCL.mjs';import {c}from'./chunk-6U6H22OR.mjs';import'./chunk-AH75LR2T.mjs';import'./chunk-RU7M6UGM.mjs';import'./chunk-2VSGDT7T.mjs';import {a as a$4}from'./chunk-B26AZRXU.mjs';import'./chunk-7BFRKEFV.mjs';import {c as c$1}from'./chunk-N3533BCE.mjs';import {a as a$7}from'./chunk-IYLF56WL.mjs';import {d as d$2}from'./chunk-ZN6MI2TU.mjs';import {d as d$1,a as a$6}from'./chunk-MHNEFL35.mjs';import {a as a$5}from'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';import*as ce from'fs';import*as x from'path';import x__default,{join}from'path';import {writeFile,mkdir,mkdtemp,rm}from'fs/promises';import {performance as performance$1}from'perf_hooks';import {tmpdir}from'os';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ var re=(s,e)=>(s.warnings||(s.warnings=[]),s.warnings.push(e),s);var ge=new Set(["click","doubleClick","hover","type","select","clearInput","copyTextFrom","randomType","randomEmail","randomNumber","randomPhone","press","scroll","scrollUntilVisible"]),he=s=>ge.has(s),be=async(s,e)=>{let r=e.args,a=r&&typeof r.selector=="string"?r.selector:null;if(!a)return null;try{let n=await s.locator(a).boundingBox({timeout:250}).catch(()=>null);return n?{x:Math.round(n.x+n.width/2),y:Math.round(n.y+n.height/2)}:null}catch{return null}},we=(s,e,r={})=>{let a=a$9(e),c=r.persistent===true;return s.evaluate(({label:n,persistent:d})=>{let C=globalThis.__skepticCursor;C&&typeof C.setCommandLabel=="function"&&C.setCommandLabel(n,{persistent:d});},{label:a,persistent:c}).catch(()=>{})},ye=s=>s.evaluate(()=>{let e=globalThis.__skepticCursor;e&&typeof e.clearCommandLabel=="function"&&e.clearCommandLabel();}).catch(()=>{}),ve=(s,e,r)=>{s.evaluate(({cmd:a,x:c,y:n})=>{let d=globalThis.__skepticCursor;!d||typeof d.recordAction!="function"||(typeof c=="number"&&typeof n=="number"?d.recordAction(a,c,n):d.recordAction(a));},{cmd:e,x:r?.x??null,y:r?.y??null}).catch(()=>{});},Ce={collectors:[],networkCaptureLimit:500,duplicateWindowMs:500,accessibilityDualEngine:false,accessibilityHtmlSnippetLimit:500,consoleCaptureLimit:200,consoleRedaction:true,autoAccessibilityAudit:false,accessibilityStandard:"WCAG21AA"},F=class{browser=null;options;constructor(e={}){this.options=e;}async launch(){let e=this.options.browserEngine??"chromium",r=await a$7(),a={chromium:r.chromium,firefox:r.firefox,webkit:r.webkit}[e];try{this.browser=await a.launch({headless:!this.options.headed});}catch(c){let n=c instanceof Error?c.message:String(c);throw n.includes("Executable doesn't exist")||n.includes("browserType.launch")?new Error(`Playwright browsers not found. Run: npx playwright install ${e}`):c}}async close(){this.browser&&(await this.browser.close(),this.browser=null);}async runTest(e,r){if(!this.browser)throw new Error("Browser not launched. Call launch() first.");let a=performance.now(),c=this.options.video??false,n=this.options.trace??false,d=false,C=this.options.outputDir??"./skeptic-output";await mkdir(C,{recursive:true});let S=e.name.replace(/[^a-zA-Z0-9_-]/g,"_"),E=e.testIndex??0,g=join(C,`${S}-${E}`);await mkdir(g,{recursive:true});let h=c?await mkdtemp(join(tmpdir(),`skeptic-video-${S}-`)):null,k=e.viewport??this.options.viewport??(this.options.deviceProfile?{width:this.options.deviceProfile.width,height:this.options.deviceProfile.height}:{width:1280,height:720}),w=this.options.videoSize??k,y=this.options.artifactConfig??a$3,m={name:e.name,file:e.file,status:"passed",duration_ms:0,steps:[],artifacts:{},...this.options.shardId!==void 0?{shardId:this.options.shardId}:{}},T="passed",b={viewport:k,...this.options.deviceProfile?.dpr?{deviceScaleFactor:this.options.deviceProfile.dpr}:{},...this.options.deviceProfile?.user_agent?{userAgent:this.options.deviceProfile.user_agent}:{},...c&&h?{recordVideo:{dir:h,size:w}}:{}},p=null,t=null;try{p=await this.browser.newContext(b),n&&(await p.tracing.start({screenshots:!0,snapshots:!0,sources:!1}),d=!0);let u=e.timeout??this.options.timeout??3e4;if(p.setDefaultTimeout(u),(e.auth==="cookies"||e.auth!=="none"&&this.options.cookies?.enabled)&&e.url)try{let{extractAndInjectCookies:o}=await import('./extractor-Y477MBN6.mjs'),i=new URL(e.url).hostname,P=await o(p,i,{browsers:this.options.cookies?.browser?[this.options.cookies.browser]:void 0});d$2.debug(`Injected ${P} cookies for ${i}`);}catch(o){d$2.warn(`Cookie extraction failed: ${o instanceof Error?o.message:String(o)}`);}if(t=await p.newPage(),c)try{await p.addInitScript({content:d$3});}catch(o){d$2.debug(`Cursor overlay attach failed: ${o instanceof Error?o.message:String(o)}`);}let v=this.options.observability??Ce,j=b$2({required:e.requiredCollectors??new Set,configured:v.collectors,config:v}),f=new b$3(t,e.url,g,x__default.dirname(e.file),u,j,y);for(let o of j)try{await o.attach(t,f);}catch(i){d$2.warn(`Collector "${o.name}" attach failed: ${i instanceof Error?i.message:String(i)}`),f.collectors.delete(o.name);}if(f.outputDir=g,e.runFn){let o="test";r?.({type:"step:start",index:0,total:1,command:o,args:{name:e.name}}),c&&we(t,o,{persistent:b$4.has(o)}).catch(()=>{});try{await e.runFn(t,f);}catch(i){let P=i instanceof Error?i.message:String(i),I={command:"test",args:{name:e.name},status:"failed",duration_ms:Math.round(performance.now()-a),error:P};if(re(I,P),m.steps.push(I),r?.({type:"step:complete",index:0,total:1,result:I}),this.options.screenshotOnFailure&&t&&!t.isClosed())try{let $=join(g,"failure.png"),ue=await t.screenshot({fullPage:!0});await writeFile($,ue),I.screenshot=$,f.addScreenshot($);}catch{}T="failed";}if(T==="passed"){let i={command:"test",args:{name:e.name},status:"passed",duration_ms:Math.round(performance.now()-a)};if(m.steps.push(i),r?.({type:"step:complete",index:0,total:1,result:i}),c&&i.status==="passed"&&he(i.command)&&t&&!t.isClosed()){let P=await be(t,i);ve(t,i.command,P);}}c&&t&&!t.isClosed()&&ye(t).catch(()=>{});}let L=f.collectors.get("accessibility"),le=v.autoAccessibilityAudit??!1;if(L instanceof a$8&&le&&f.abortReason===null&&t&&!t.isClosed()&&!(await L.snapshot()!==void 0))try{await L.audit({standard:v.accessibilityStandard??"WCAG21AA",...v.accessibilityImpacts?{impacts:v.accessibilityImpacts}:{}});}catch(i){d$2.warn(`Auto a11y audit failed: ${i instanceof Error?i.message:String(i)}`);}let _={};f.inTeardown=!0;try{for(let o of f.collectors.values())try{let i=await o.snapshot();i!=null&&(_[o.name]=i);}catch(i){d$2.warn(`Collector "${o.name}" snapshot failed: ${i instanceof Error?i.message:String(i)}`);}for(let o of f.collectors.values())try{await o.detach();}catch(i){d$2.warn(`Collector "${o.name}" detach failed: ${i instanceof Error?i.message:String(i)}`);}}finally{f.inTeardown=!1;}if(y.visualSettle.enabled&&t&&!t.isClosed())try{await c$1(t,f,y.visualSettle);}catch(o){d$2.debug(`Pre-video settle failed: ${o instanceof Error?o.message:String(o)}`);}if(f.screenshots.length>0&&(m.artifacts.screenshots=[...f.screenshots]),c&&t)try{let o=t.video();if(o){let i=join(g,`${S}.webm`);await t.close(),t=null,await o.saveAs(i),h&&await rm(h,{recursive:!0,force:!0}).catch(()=>{}),m.artifacts.video={path:i,width:w.width,height:w.height},d$2.info(`Video saved to ${i}`);}}catch(o){d$2.warn(`Video save failed: ${o instanceof Error?o.message:String(o)}`);}if(d&&p)try{let o=join(g,`${S}.trace.zip`);await p.tracing.stop({path:o}),m.artifacts.trace=o,d=!1,d$2.info(`Trace saved. View with: npx playwright show-trace ${o}`);}catch(o){d$2.warn(`Trace save failed: ${o instanceof Error?o.message:String(o)}`);}return m.status=T,m.duration_ms=Math.round(performance.now()-a),Object.keys(_).length>0&&(m.metrics=_),y.writeSidecars&&await c$2({testDir:g,metrics:_,artifacts:m.artifacts,observabilityConfig:v}),m}finally{if(d&&p)try{let u=join(g,`${S}.trace.zip`);await p.tracing.stop({path:u});}catch{}t&&!t.isClosed()&&await t.close().catch(()=>{}),p&&await p.close().catch(()=>{}),h&&await rm(h,{recursive:true,force:true}).catch(()=>{});}}};var Se=s=>s.tui!==false,ke=()=>new Date().toISOString().replace(/[:.]/g,"-"),Pe=s=>{try{return new URL(s).hostname.replace(/[^a-zA-Z0-9_-]/g,"_")||"page"}catch{return "page"}},tt=async(s,e)=>{let r=d({configPath:e.config,overrides:{}}),a$7=e.output??x.join(r.output.dir??d$1,`observe-${ke()}`);ce.mkdirSync(a$7,{recursive:true});let c$1=e.device??r.browser.device,n=c$1?c(c$1):void 0,d$3=n?{width:n.width,height:n.height}:r.browser.viewport,C=n?{width:n.width,height:n.height,dpr:n.dpr,user_agent:n.userAgent}:void 0,S=e.videoSize?b(e.videoSize):d$3,E=e.timeout??r.browser.timeout,g=new Set(["performance","network","console","accessibility"]),h=`observe ${Pe(s)}`,k=`skeptic observe ${s}`,w=[...Se(e)?[new a]:[],new a$1(a$7),new a$2(a$7)],y={name:h,file:k,testIndex:0};for(let b of w)b.onRunStart?.({tests:[{name:h,file:k,stepCount:1}],totalTests:1}),b.onTestStart(y);let m=new F({headed:e.headed??!r.browser.headless,timeout:E,outputDir:a$7,browserEngine:r.browser.engine,viewport:d$3,deviceProfile:C,video:e.video??true,videoSize:S,trace:e.trace??true,screenshotOnFailure:true,cookies:e.cookies??r.auth.cookies?{enabled:e.cookies??r.auth.cookies,...e.cookiesFrom?{browser:e.cookiesFrom}:{}}:void 0,observability:{collectors:[...g],networkCaptureLimit:r.observability.networkCaptureLimit,duplicateWindowMs:r.observability.duplicateWindowMs,accessibilityDualEngine:true,accessibilityHtmlSnippetLimit:r.observability.accessibilityHtmlSnippetLimit,consoleCaptureLimit:r.observability.consoleCaptureLimit,consoleRedaction:r.observability.consoleRedaction,autoAccessibilityAudit:true,accessibilityStandard:r.observability.accessibilityStandard,...r.observability.accessibilityImpacts?{accessibilityImpacts:r.observability.accessibilityImpacts}:{},accessibilityMaxRulesPerImpact:r.observability.accessibilityMaxRulesPerImpact},artifactConfig:{...a$3,fullPageScreenshots:e.fullPage??r.observability.fullPageScreenshots,blankFrameDetection:r.observability.blankFrameDetection,writeSidecars:true}}),T=performance$1.now();try{await m.launch();let b=await m.runTest({url:s,name:h,file:k,timeout:E,viewport:d$3,requiredCollectors:g,runFn:async(t,u)=>{await t.goto(s,{waitUntil:e.waitUntil??"domcontentloaded"}),e.wait&&e.wait>0&&await t.waitForTimeout(e.wait),await a$4(t,u,"01-page",{fullPage:e.fullPage??r.observability.fullPageScreenshots}),await a$4(t,u,"02-page-annotated",{annotate:!0,fullPage:e.fullPage??r.observability.fullPageScreenshots});let A=await b$1(t,u,{compact:!0}),v={url:t.url(),title:await t.title(),yaml:A.yaml,stats:A.stats,refs:[...A.refs.values()]};await writeFile(x.join(u.testDir,"snapshot.txt"),A.yaml,"utf-8"),await writeFile(x.join(u.testDir,"snapshot.json"),JSON.stringify(v,null,2),"utf-8");}},t=>{if(t.type==="step:start")for(let u of w)u.onStepStart?.({command:t.command,args:t.args},t.index,t.total,y);else for(let u of w)u.onStepComplete(t.result,t.index,t.total,y);});for(let t of w)t.onTestComplete(b,y);let p={total:1,passed:b.status==="passed"?1:0,failed:b.status==="passed"?0:1,skipped:0,duration_ms:Math.round(performance$1.now()-T),tests:[b]};for(let t of w)await t.onRunComplete(p);d$2.raw(""),d$2.raw(a$5.bold(` ${a$6} observe artifacts`));for(let[t,u]of [["Report",x.join(a$7,"report.html")],["JSON",x.join(a$7,"results.json")],["Output",a$7]])d$2.raw(` ${a$5.dim(t.padEnd(8))} ${a$5.cyan(u)}`);d$2.raw(""),process.exitCode=b.status==="passed"?0:1;}finally{await m.close().catch(()=>{});}};export{Se as observeShowsLiveConsole,tt as runObserve};