@skyramp/mcp 0.3.7 → 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.
- package/build/playwright/registerPlaywrightTools.js +1 -0
- package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +22 -1
- package/build/prompts/test-maintenance/actionsInstructions.d.ts +4 -0
- package/build/prompts/test-maintenance/actionsInstructions.js +14 -2
- package/build/prompts/test-maintenance/uiDriftAnalysisSections.js +4 -1
- package/build/prompts/test-recommendation/diffExecutionPlan.js +41 -9
- package/build/prompts/test-recommendation/fullRepoCatalog.js +3 -2
- package/build/prompts/test-recommendation/recommendationSections.js +3 -3
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +2 -2
- package/build/prompts/test-recommendation/scopeAssessment.js +58 -76
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +14 -1
- package/build/prompts/testbot/testbot-prompts.js +35 -15
- package/build/recommendation/budgeters/diversityBalancedBudgeter.js +39 -5
- package/build/recommendation/budgeters/shared.d.ts +21 -8
- package/build/recommendation/budgeters/shared.js +134 -56
- package/build/recommendation/planRanker.d.ts +5 -3
- package/build/recommendation/planRanker.js +1 -1
- package/build/services/containerEnv.d.ts +1 -1
- package/build/services/containerEnv.js +12 -0
- package/build/tools/executeSkyrampTestTool.d.ts +80 -0
- package/build/tools/executeSkyrampTestTool.js +246 -19
- package/build/tools/submitReportTool.d.ts +5 -5
- package/build/tools/submitReportTool.js +11 -2
- package/build/tools/test-management/actionsTool.js +71 -3
- package/build/tools/test-management/analyzeChangesTool.d.ts +10 -0
- package/build/tools/test-management/analyzeChangesTool.js +73 -0
- package/build/tools/test-management/registerTestPlanTool.d.ts +3 -3
- package/build/tools/test-management/registerTestPlanTool.js +29 -8
- package/build/types/RepositoryAnalysis.d.ts +10 -10
- package/build/types/TestAnalysis.d.ts +12 -0
- package/build/types/TestExecution.d.ts +4 -0
- package/build/types/TestRecommendation.d.ts +11 -1
- package/build/types/TestRecommendation.js +34 -0
- package/build/utils/AnalysisStateManager.d.ts +7 -0
- package/build/utils/assertion-verify/ui-lints.d.ts +0 -5
- package/build/utils/assertion-verify/ui-lints.js +32 -0
- package/build/utils/frontendSelectors.d.ts +33 -0
- package/build/utils/frontendSelectors.js +196 -5
- package/build/utils/pathSignatures.d.ts +4 -1
- package/build/utils/pathSignatures.js +14 -2
- package/build/utils/planOnlyMode.d.ts +33 -0
- package/build/utils/planOnlyMode.js +40 -0
- package/build/utils/rebaselineSnapshots.d.ts +24 -0
- package/build/utils/rebaselineSnapshots.js +65 -0
- package/build/utils/removedUiElements.d.ts +34 -0
- package/build/utils/removedUiElements.js +153 -0
- package/build/utils/reportVerification.d.ts +7 -6
- package/build/utils/reportVerification.js +68 -4
- package/build/utils/scenarioDrafting.d.ts +1 -1
- package/build/utils/scenarioDrafting.js +1 -1
- package/build/utils/versions.d.ts +3 -3
- package/build/utils/versions.js +1 -1
- package/node_modules/playwright/lib/mcp/skyramp/assertHiddenTool.js +56 -0
- package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +2 -1
- package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +10 -0
- package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +4 -1
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +160 -1
- package/node_modules/playwright/lib/mcp/test/skyRampExport.js +4 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +1 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderSignalProcessor.js +2 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder.js +5 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.-Id052Lr.js → index.B7KbSQcC.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +1 -1
- package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderSignalProcessor.ts +7 -0
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder.ts +6 -1
- package/node_modules/playwright/package.json +1 -1
- package/package.json +3 -3
|
@@ -444,7 +444,7 @@ function assertActionToJsonl(action, pageGuid, timestamp) {
|
|
|
444
444
|
}
|
|
445
445
|
} else {
|
|
446
446
|
const parts = code.split(":");
|
|
447
|
-
if (assertType === "visible") {
|
|
447
|
+
if (assertType === "visible" || assertType === "hidden") {
|
|
448
448
|
selector = parts.slice(1).join(":");
|
|
449
449
|
} else if (assertType === "text") {
|
|
450
450
|
substring = parts[parts.length - 1] === "true";
|
|
@@ -455,12 +455,14 @@ function assertActionToJsonl(action, pageGuid, timestamp) {
|
|
|
455
455
|
selector = parts.slice(1, parts.length - 1).join(":");
|
|
456
456
|
}
|
|
457
457
|
}
|
|
458
|
-
const locator = selectorToLocator(selector);
|
|
458
|
+
const locator = args.locator && typeof args.locator === "object" ? args.locator : selectorToLocator(selector);
|
|
459
459
|
switch (assertType) {
|
|
460
460
|
case "text":
|
|
461
461
|
return JSON.stringify({ name: "assertText", selector, text: expected, substring, locator, ...base });
|
|
462
462
|
case "visible":
|
|
463
463
|
return JSON.stringify({ name: "assertVisible", selector, locator, ...base });
|
|
464
|
+
case "hidden":
|
|
465
|
+
return JSON.stringify({ name: "assertHidden", selector, locator, ...base });
|
|
464
466
|
case "value":
|
|
465
467
|
return JSON.stringify({ name: "assertValue", selector, value: expected, locator, ...base });
|
|
466
468
|
case "checked":
|
|
@@ -50,6 +50,8 @@ class RecorderSignalProcessor {
|
|
|
50
50
|
generateGoto = false;
|
|
51
51
|
else if (signal.isReload)
|
|
52
52
|
generateGoto = !recentReloadUserAction;
|
|
53
|
+
else if (signal.fromBlankPage)
|
|
54
|
+
generateGoto = true;
|
|
53
55
|
else if (!recentNavUserAction)
|
|
54
56
|
generateGoto = true;
|
|
55
57
|
if (generateGoto) {
|
|
@@ -558,7 +558,8 @@ class Recorder extends import_events.default {
|
|
|
558
558
|
const isSameDocument = !!event && !event.newDocument;
|
|
559
559
|
this._prevFrameUrls.set(frame, frame.url());
|
|
560
560
|
const url = userInitiatedNavigationUrl(event) ?? frame.url();
|
|
561
|
-
|
|
561
|
+
const fromBlankPage = isBlankUrl(prevUrl) && !isBlankUrl(url);
|
|
562
|
+
this._signalProcessor.signal(pageAlias, frame, { name: "navigation", url, isReload, isSameDocument, fromBlankPage });
|
|
562
563
|
}
|
|
563
564
|
_onPopup(page, popup) {
|
|
564
565
|
const pageAlias = this._pageAliases.get(page);
|
|
@@ -587,6 +588,9 @@ function userInitiatedNavigationUrl(event) {
|
|
|
587
588
|
request = request.redirectedFrom();
|
|
588
589
|
return request.url();
|
|
589
590
|
}
|
|
591
|
+
function isBlankUrl(url) {
|
|
592
|
+
return !url || url === "about:blank";
|
|
593
|
+
}
|
|
590
594
|
function languageForFile(file) {
|
|
591
595
|
if (file.endsWith(".py"))
|
|
592
596
|
return "python";
|
|
@@ -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.
|
|
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)})();
|
package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html
CHANGED
|
@@ -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
|
|
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">
|
|
@@ -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
|
-
|
|
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';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyramp/mcp",
|
|
3
|
-
"version": "0.3.
|
|
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.
|
|
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.
|
|
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",
|