@skyramp/mcp 0.3.8 → 0.3.9-rc.1

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 (49) hide show
  1. package/build/playwright/registerPlaywrightTools.js +1 -0
  2. package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +22 -1
  3. package/build/prompts/test-maintenance/actionsInstructions.d.ts +4 -0
  4. package/build/prompts/test-maintenance/actionsInstructions.js +14 -2
  5. package/build/prompts/test-maintenance/uiDriftAnalysisSections.js +4 -1
  6. package/build/prompts/test-recommendation/diffExecutionPlan.js +1 -0
  7. package/build/prompts/test-recommendation/scopeAssessment.js +1 -1
  8. package/build/prompts/testbot/testbot-prompts.js +10 -7
  9. package/build/services/containerEnv.d.ts +1 -1
  10. package/build/services/containerEnv.js +12 -0
  11. package/build/tools/executeSkyrampTestTool.d.ts +80 -0
  12. package/build/tools/executeSkyrampTestTool.js +246 -19
  13. package/build/tools/submitReportTool.d.ts +5 -5
  14. package/build/tools/submitReportTool.js +5 -1
  15. package/build/tools/test-management/actionsTool.js +71 -3
  16. package/build/tools/test-management/analyzeChangesTool.d.ts +10 -0
  17. package/build/tools/test-management/analyzeChangesTool.js +73 -0
  18. package/build/types/TestAnalysis.d.ts +12 -0
  19. package/build/types/TestExecution.d.ts +4 -0
  20. package/build/utils/AnalysisStateManager.d.ts +7 -0
  21. package/build/utils/assertion-verify/ui-lints.d.ts +0 -5
  22. package/build/utils/assertion-verify/ui-lints.js +32 -0
  23. package/build/utils/frontendSelectors.d.ts +33 -0
  24. package/build/utils/frontendSelectors.js +196 -5
  25. package/build/utils/rebaselineSnapshots.d.ts +24 -0
  26. package/build/utils/rebaselineSnapshots.js +65 -0
  27. package/build/utils/removedUiElements.d.ts +34 -0
  28. package/build/utils/removedUiElements.js +153 -0
  29. package/build/utils/reportVerification.d.ts +2 -6
  30. package/build/utils/reportVerification.js +61 -2
  31. package/build/utils/versions.d.ts +3 -3
  32. package/build/utils/versions.js +1 -1
  33. package/node_modules/playwright/lib/mcp/skyramp/assertHiddenTool.js +56 -0
  34. package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +2 -1
  35. package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +10 -0
  36. package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +4 -1
  37. package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +160 -1
  38. package/node_modules/playwright/lib/mcp/test/skyRampExport.js +4 -2
  39. package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +1 -0
  40. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderSignalProcessor.js +2 -0
  41. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder.js +5 -1
  42. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.-Id052Lr.js → index.B7KbSQcC.js} +1 -1
  43. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +1 -1
  44. package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
  45. package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -1
  46. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderSignalProcessor.ts +7 -0
  47. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder.ts +6 -1
  48. package/node_modules/playwright/package.json +1 -1
  49. package/package.json +3 -3
@@ -1,2 +1,2 @@
1
- import{T as x,r,a as C,W as F,j as e,D as z,b as I,c as P,d as A,e as O,f as V}from"./assets/defaultSettingsView-Bwr1eMKC.js";const $=()=>{const[o,c]=r.useState(!1),[n,l]=r.useState(),[h,u]=r.useState(),[p,b]=r.useState(N),[f,j]=r.useState({done:0,total:0}),[k,v]=r.useState(!1),[y,m]=r.useState(null),[T,R]=r.useState(null),[U,E]=r.useState(!1),g=r.useCallback(t=>{const s=new URL(window.location.href);if(!t.length)return;const i=t.item(0),a=URL.createObjectURL(i);s.searchParams.append("trace",a);const d=s.toString();window.history.pushState({},"",d),l(a),u(i.name),v(!1),m(null)},[]);r.useEffect(()=>{const t=async s=>{var a;if(!((a=s.clipboardData)!=null&&a.files.length))return;const i=["application/zip","application/x-zip-compressed"];for(const d of s.clipboardData.files)if(!i.includes(d.type))return;s.preventDefault(),g(s.clipboardData.files)};return document.addEventListener("paste",t),()=>document.removeEventListener("paste",t)}),r.useEffect(()=>{const t=s=>{const{method:i,params:a}=s.data;if(i!=="load"||!((a==null?void 0:a.trace)instanceof Blob))return;const d=new File([a.trace],"trace.zip",{type:"application/zip"}),w=new DataTransfer;w.items.add(d),g(w.files)};return window.addEventListener("message",t),()=>window.removeEventListener("message",t)});const W=r.useCallback(t=>{t.preventDefault(),g(t.dataTransfer.files)},[g]),M=r.useCallback(t=>{t.preventDefault(),t.target.files&&g(t.target.files)},[g]);r.useEffect(()=>{const t=new URL(window.location.href).searchParams,s=t.get("trace");if(c(t.has("isServer")),s!=null&&s.startsWith("file:")){R(s||null);return}if(t.has("isServer")){const i=new URLSearchParams(window.location.search).get("ws"),a=new URL(`../${i}`,window.location.toString());a.protocol=window.location.protocol==="https:"?"wss:":"ws:";const d=new C(new F(a));d.onLoadTraceRequested(async w=>{l(w.traceUrl),v(!1),m(null)}),d.initialize({}).catch(()=>{})}else s&&!s.startsWith("blob:")&&l(s)},[]);const S=r.useCallback(async t=>{const s=new URLSearchParams;s.set("trace",t);const i=await fetch(`contexts?${s.toString()}`);if(!i.ok){const{error:w}=await i.json();return m(w),w}const a=await i.json(),d=new x(t,a);j({done:0,total:0}),m(null),b(d)},[]);r.useEffect(()=>{(async()=>{if(!n){b(N);return}const t=s=>{s.data.method==="progress"&&j(s.data.params)};try{navigator.serviceWorker.addEventListener("message",t),j({done:0,total:1});let s=await S(n);s!=null&&s.includes("please grant permission for Local Network Access")&&(await fetch(n,{method:"HEAD",headers:{"x-pw-serviceworker":"skip"}}),s=await S(n)),s&&(o||l(void 0))}finally{navigator.serviceWorker.removeEventListener("message",t)}})()},[o,n,h,S]);const D=f.done!==f.total&&f.total!==0&&!y;r.useEffect(()=>{if(D){const t=setTimeout(()=>{E(!0)},200);return()=>clearTimeout(t)}else E(!1)},[D]);const L=!!(!o&&!k&&!T&&(!n||y));return e.jsxs("div",{className:"vbox workbench-loader",onDragOver:t=>{t.preventDefault(),t.dataTransfer.types.includes("Files")&&v(!0)},children:[e.jsxs("div",{className:"hbox header",...L?{inert:!0}:{},children:[e.jsx("div",{className:"logo",children:e.jsx("img",{src:"playwright-logo.svg",alt:"Playwright logo"})}),e.jsx("div",{className:"product",children:"Playwright"}),p.title&&e.jsx("div",{className:"title",children:p.title}),e.jsx("div",{className:"spacer"}),e.jsx(z,{icon:"settings-gear",title:"Settings",dialogDataTestId:"settings-toolbar-dialog",children:e.jsx(I,{location:"trace-viewer"})})]}),e.jsx(P,{model:p,inert:L}),T&&e.jsxs("div",{className:"drop-target",children:[e.jsx("div",{children:"Trace Viewer uses Service Workers to show traces. To view trace:"}),e.jsxs("div",{style:{paddingTop:20},children:[e.jsxs("div",{children:["1. Click ",e.jsx("a",{href:T,children:"here"})," to put your trace into the download shelf"]}),e.jsxs("div",{children:["2. Go to ",e.jsx("a",{href:"https://trace.playwright.dev",children:"trace.playwright.dev"})]}),e.jsx("div",{children:"3. Drop the trace from the download shelf into the page"})]})]}),e.jsx(A,{open:U,isModal:!0,className:"progress-dialog",children:e.jsxs("div",{className:"progress-content",children:[e.jsx("div",{className:"title",role:"heading","aria-level":1,children:"Loading Playwright Trace..."}),e.jsx("div",{className:"progress-wrapper",children:e.jsx("div",{className:"inner-progress",style:{width:f.total?100*f.done/f.total+"%":0}})})]})}),L&&e.jsxs("div",{className:"drop-target",children:[e.jsx("div",{className:"processing-error",role:"alert",children:y}),e.jsx("div",{className:"title",role:"heading","aria-level":1,children:"Drop Playwright Trace to load"}),e.jsx("div",{children:"or"}),e.jsx("button",{onClick:()=>{const t=document.createElement("input");t.type="file",t.click(),t.addEventListener("change",s=>M(s))},type:"button",children:"Select file"}),e.jsx("div",{className:"info",children:"Playwright Trace Viewer is a Progressive Web App, it does not send your trace anywhere, it opens it locally."}),e.jsxs("div",{className:"version",children:["Playwright v","1.58.2-skyramp.8.14.6"]})]}),o&&!n&&e.jsx("div",{className:"drop-target",children:e.jsx("div",{className:"title",children:"Select test to see the trace"})}),k&&e.jsx("div",{className:"drop-target",onDragLeave:()=>{v(!1)},onDrop:t=>W(t),children:e.jsx("div",{className:"title",children:"Release to analyse the Playwright Trace"})})]})},N=new x("",[]),q=({traceJson:o})=>{const[c,n]=r.useState(void 0),[l,h]=r.useState(0),u=r.useRef(null);return r.useEffect(()=>(u.current&&clearTimeout(u.current),u.current=setTimeout(async()=>{try{const p=await B(o);n(p)}catch{const p=new x("",[]);n(p)}finally{h(l+1)}},500),()=>{u.current&&clearTimeout(u.current)}),[o,l]),e.jsx(P,{isLive:!0,model:c})};async function B(o){const c=new URLSearchParams;c.set("trace",o);const l=await(await fetch(`contexts?${c.toString()}`)).json();return new x(o,l)}(async()=>{const o=new URLSearchParams(window.location.search);if(O(),window.location.protocol!=="file:"){if(o.get("isUnderTest")==="true"&&await new Promise(h=>setTimeout(h,1e3)),!navigator.serviceWorker)throw new Error(`Service workers are not supported.
1
+ import{T as x,r,a as C,W as F,j as e,D as z,b as I,c as P,d as A,e as O,f as V}from"./assets/defaultSettingsView-Bwr1eMKC.js";const $=()=>{const[o,c]=r.useState(!1),[n,l]=r.useState(),[h,u]=r.useState(),[p,b]=r.useState(N),[f,j]=r.useState({done:0,total:0}),[k,v]=r.useState(!1),[y,m]=r.useState(null),[T,R]=r.useState(null),[U,E]=r.useState(!1),g=r.useCallback(t=>{const s=new URL(window.location.href);if(!t.length)return;const i=t.item(0),a=URL.createObjectURL(i);s.searchParams.append("trace",a);const d=s.toString();window.history.pushState({},"",d),l(a),u(i.name),v(!1),m(null)},[]);r.useEffect(()=>{const t=async s=>{var a;if(!((a=s.clipboardData)!=null&&a.files.length))return;const i=["application/zip","application/x-zip-compressed"];for(const d of s.clipboardData.files)if(!i.includes(d.type))return;s.preventDefault(),g(s.clipboardData.files)};return document.addEventListener("paste",t),()=>document.removeEventListener("paste",t)}),r.useEffect(()=>{const t=s=>{const{method:i,params:a}=s.data;if(i!=="load"||!((a==null?void 0:a.trace)instanceof Blob))return;const d=new File([a.trace],"trace.zip",{type:"application/zip"}),w=new DataTransfer;w.items.add(d),g(w.files)};return window.addEventListener("message",t),()=>window.removeEventListener("message",t)});const W=r.useCallback(t=>{t.preventDefault(),g(t.dataTransfer.files)},[g]),M=r.useCallback(t=>{t.preventDefault(),t.target.files&&g(t.target.files)},[g]);r.useEffect(()=>{const t=new URL(window.location.href).searchParams,s=t.get("trace");if(c(t.has("isServer")),s!=null&&s.startsWith("file:")){R(s||null);return}if(t.has("isServer")){const i=new URLSearchParams(window.location.search).get("ws"),a=new URL(`../${i}`,window.location.toString());a.protocol=window.location.protocol==="https:"?"wss:":"ws:";const d=new C(new F(a));d.onLoadTraceRequested(async w=>{l(w.traceUrl),v(!1),m(null)}),d.initialize({}).catch(()=>{})}else s&&!s.startsWith("blob:")&&l(s)},[]);const S=r.useCallback(async t=>{const s=new URLSearchParams;s.set("trace",t);const i=await fetch(`contexts?${s.toString()}`);if(!i.ok){const{error:w}=await i.json();return m(w),w}const a=await i.json(),d=new x(t,a);j({done:0,total:0}),m(null),b(d)},[]);r.useEffect(()=>{(async()=>{if(!n){b(N);return}const t=s=>{s.data.method==="progress"&&j(s.data.params)};try{navigator.serviceWorker.addEventListener("message",t),j({done:0,total:1});let s=await S(n);s!=null&&s.includes("please grant permission for Local Network Access")&&(await fetch(n,{method:"HEAD",headers:{"x-pw-serviceworker":"skip"}}),s=await S(n)),s&&(o||l(void 0))}finally{navigator.serviceWorker.removeEventListener("message",t)}})()},[o,n,h,S]);const D=f.done!==f.total&&f.total!==0&&!y;r.useEffect(()=>{if(D){const t=setTimeout(()=>{E(!0)},200);return()=>clearTimeout(t)}else E(!1)},[D]);const L=!!(!o&&!k&&!T&&(!n||y));return e.jsxs("div",{className:"vbox workbench-loader",onDragOver:t=>{t.preventDefault(),t.dataTransfer.types.includes("Files")&&v(!0)},children:[e.jsxs("div",{className:"hbox header",...L?{inert:!0}:{},children:[e.jsx("div",{className:"logo",children:e.jsx("img",{src:"playwright-logo.svg",alt:"Playwright logo"})}),e.jsx("div",{className:"product",children:"Playwright"}),p.title&&e.jsx("div",{className:"title",children:p.title}),e.jsx("div",{className:"spacer"}),e.jsx(z,{icon:"settings-gear",title:"Settings",dialogDataTestId:"settings-toolbar-dialog",children:e.jsx(I,{location:"trace-viewer"})})]}),e.jsx(P,{model:p,inert:L}),T&&e.jsxs("div",{className:"drop-target",children:[e.jsx("div",{children:"Trace Viewer uses Service Workers to show traces. To view trace:"}),e.jsxs("div",{style:{paddingTop:20},children:[e.jsxs("div",{children:["1. Click ",e.jsx("a",{href:T,children:"here"})," to put your trace into the download shelf"]}),e.jsxs("div",{children:["2. Go to ",e.jsx("a",{href:"https://trace.playwright.dev",children:"trace.playwright.dev"})]}),e.jsx("div",{children:"3. Drop the trace from the download shelf into the page"})]})]}),e.jsx(A,{open:U,isModal:!0,className:"progress-dialog",children:e.jsxs("div",{className:"progress-content",children:[e.jsx("div",{className:"title",role:"heading","aria-level":1,children:"Loading Playwright Trace..."}),e.jsx("div",{className:"progress-wrapper",children:e.jsx("div",{className:"inner-progress",style:{width:f.total?100*f.done/f.total+"%":0}})})]})}),L&&e.jsxs("div",{className:"drop-target",children:[e.jsx("div",{className:"processing-error",role:"alert",children:y}),e.jsx("div",{className:"title",role:"heading","aria-level":1,children:"Drop Playwright Trace to load"}),e.jsx("div",{children:"or"}),e.jsx("button",{onClick:()=>{const t=document.createElement("input");t.type="file",t.click(),t.addEventListener("change",s=>M(s))},type:"button",children:"Select file"}),e.jsx("div",{className:"info",children:"Playwright Trace Viewer is a Progressive Web App, it does not send your trace anywhere, it opens it locally."}),e.jsxs("div",{className:"version",children:["Playwright v","1.58.2-skyramp.8.14.9"]})]}),o&&!n&&e.jsx("div",{className:"drop-target",children:e.jsx("div",{className:"title",children:"Select test to see the trace"})}),k&&e.jsx("div",{className:"drop-target",onDragLeave:()=>{v(!1)},onDrop:t=>W(t),children:e.jsx("div",{className:"title",children:"Release to analyse the Playwright Trace"})})]})},N=new x("",[]),q=({traceJson:o})=>{const[c,n]=r.useState(void 0),[l,h]=r.useState(0),u=r.useRef(null);return r.useEffect(()=>(u.current&&clearTimeout(u.current),u.current=setTimeout(async()=>{try{const p=await B(o);n(p)}catch{const p=new x("",[]);n(p)}finally{h(l+1)}},500),()=>{u.current&&clearTimeout(u.current)}),[o,l]),e.jsx(P,{isLive:!0,model:c})};async function B(o){const c=new URLSearchParams;c.set("trace",o);const l=await(await fetch(`contexts?${c.toString()}`)).json();return new x(o,l)}(async()=>{const o=new URLSearchParams(window.location.search);if(O(),window.location.protocol!=="file:"){if(o.get("isUnderTest")==="true"&&await new Promise(h=>setTimeout(h,1e3)),!navigator.serviceWorker)throw new Error(`Service workers are not supported.
2
2
  Make sure to serve the Trace Viewer (${window.location}) via HTTPS or localhost.`);navigator.serviceWorker.register("sw.bundle.js"),navigator.serviceWorker.controller||await new Promise(h=>{navigator.serviceWorker.oncontrollerchange=()=>h()}),setInterval(function(){fetch("ping")},1e4)}const c=o.get("trace"),l=(c==null?void 0:c.endsWith(".json"))?e.jsx(q,{traceJson:c}):e.jsx($,{});V.createRoot(document.querySelector("#root")).render(l)})();
@@ -7,7 +7,7 @@
7
7
  <link rel="icon" href="./playwright-logo.svg" type="image/svg+xml">
8
8
  <link rel="manifest" href="./manifest.webmanifest">
9
9
  <title>Playwright Trace Viewer</title>
10
- <script type="module" crossorigin src="./index.-Id052Lr.js"></script>
10
+ <script type="module" crossorigin src="./index.B7KbSQcC.js"></script>
11
11
  <link rel="modulepreload" crossorigin href="./assets/defaultSettingsView-Bwr1eMKC.js">
12
12
  <link rel="stylesheet" crossorigin href="./defaultSettingsView.7ch9cixO.css">
13
13
  <link rel="stylesheet" crossorigin href="./index.BVu7tZDe.css">
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright-core",
3
- "version": "1.58.2-skyramp.8.14.6",
3
+ "version": "1.58.2-skyramp.8.14.9",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -117,7 +117,7 @@ const _ACTION_NAMES = new Set<string>([
117
117
  'check', 'click', 'hover', 'closePage', 'fill',
118
118
  'navigate', 'openPage', 'press', 'select', 'uncheck',
119
119
  'setInputFiles', 'assertText', 'assertValue', 'assertChecked',
120
- 'assertVisible', 'assertDisabled', 'assertCount', 'assertSnapshot', 'visualSnapshot', 'assertTableCell',
120
+ 'assertVisible', 'assertDisabled', 'assertCount', 'assertHidden', 'assertSnapshot', 'visualSnapshot', 'assertTableCell',
121
121
  'dragTo', 'diagramNodeAdd', 'diagramLinkAdd', 'selectArea', 'tableSnapshot', 'domSnapshot', 'fileChooser',
122
122
  'penTool', 'mouse.wheel', 'mouse.move', 'mouse.down', 'mouse.up',
123
123
  'modalOpen', 'modalClose', 'waitForTimeout', 'evaluate',
@@ -63,6 +63,13 @@ export class RecorderSignalProcessor {
63
63
  generateGoto = false; // SPA pushState/replaceState/popstate: not a real navigation
64
64
  else if (signal.isReload)
65
65
  generateGoto = !recentReloadUserAction; // Browser reload button: capture only when no recent user action triggered it
66
+ // First navigation off the blank start page: never suppress it. A real recording
67
+ // starts on an empty about:blank, so a click there is a stray focus click and the
68
+ // navigation came from the address bar. A blank page given content programmatically
69
+ // could in principle navigate itself, which would make this goto redundant -- but a
70
+ // redundant goto is a far cheaper failure than a spec with no navigation at all.
71
+ else if (signal.fromBlankPage)
72
+ generateGoto = true;
66
73
  else if (!recentNavUserAction)
67
74
  generateGoto = true;
68
75
 
@@ -677,7 +677,8 @@ export class Recorder extends EventEmitter<RecorderEventMap> implements Instrume
677
677
  const isSameDocument = !!event && !event.newDocument;
678
678
  this._prevFrameUrls.set(frame, frame.url());
679
679
  const url = userInitiatedNavigationUrl(event) ?? frame.url();
680
- this._signalProcessor.signal(pageAlias!, frame, { name: 'navigation', url, isReload, isSameDocument });
680
+ const fromBlankPage = isBlankUrl(prevUrl) && !isBlankUrl(url);
681
+ this._signalProcessor.signal(pageAlias!, frame, { name: 'navigation', url, isReload, isSameDocument, fromBlankPage });
681
682
  }
682
683
 
683
684
  private _onPopup(page: Page, popup: Page) {
@@ -716,6 +717,10 @@ function userInitiatedNavigationUrl(event?: NavigationEvent): string | undefined
716
717
  return request.url();
717
718
  }
718
719
 
720
+ function isBlankUrl(url: string | undefined): boolean {
721
+ return !url || url === 'about:blank';
722
+ }
723
+
719
724
  function languageForFile(file: string): Language {
720
725
  if (file.endsWith('.py'))
721
726
  return 'python';
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyramp/playwright",
3
- "version": "1.58.2-skyramp.8.14.6",
3
+ "version": "1.58.2-skyramp.8.14.9",
4
4
  "description": "Skyramp's fork of Playwright with trace recording for UI test generation",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyramp/mcp",
3
- "version": "0.3.8",
3
+ "version": "0.3.9-rc.1",
4
4
  "main": "build/index.js",
5
5
  "exports": {
6
6
  ".": "./build/index.js",
@@ -70,12 +70,12 @@
70
70
  "dependencies": {
71
71
  "@modelcontextprotocol/sdk": "^1.24.3",
72
72
  "@playwright/test": "^1.55.0",
73
- "@skyramp/skyramp": "1.3.40",
73
+ "@skyramp/skyramp": "1.3.42",
74
74
  "dockerode": "^5.0.0",
75
75
  "fast-glob": "^3.3.3",
76
76
  "js-yaml": "^4.1.1",
77
77
  "picomatch": "^4.0.5",
78
- "playwright": "file:vendor/skyramp-playwright-1.58.2-skyramp.8.14.6.tgz",
78
+ "playwright": "file:vendor/skyramp-playwright-1.58.2-skyramp.8.14.9.tgz",
79
79
  "simple-git": "^3.30.0",
80
80
  "ts-is-record": "^3.0.5",
81
81
  "typescript": "^5.8.3",