@skyramp/mcp 0.3.0-rc.1 → 0.3.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.
- package/build/prompts/test-maintenance/actionsInstructions.js +4 -2
- package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +9 -0
- package/build/prompts/test-maintenance/drift-analysis-prompt.js +8 -7
- package/build/prompts/test-maintenance/driftAnalysisSections.js +4 -5
- package/build/prompts/test-maintenance/driftAnalysisShared.d.ts +11 -0
- package/build/prompts/test-maintenance/driftAnalysisShared.js +22 -6
- package/build/prompts/test-maintenance/uiDriftAnalysisSections.js +23 -31
- package/build/prompts/test-recommendation/diffExecutionPlan.d.ts +7 -1
- package/build/prompts/test-recommendation/diffExecutionPlan.js +20 -6
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +10 -1
- package/build/prompts/test-recommendation/scopeAssessment.js +27 -2
- package/build/prompts/test-recommendation/scopeAssessment.test.js +35 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +5 -1
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +61 -0
- package/build/prompts/testbot/testbot-prompts.js +7 -5
- package/build/prompts/testbot/testbot-prompts.test.js +1 -1
- package/build/services/AnalyticsService.js +37 -2
- package/build/services/TestDiscoveryService.d.ts +38 -4
- package/build/services/TestDiscoveryService.js +187 -16
- package/build/services/TestDiscoveryService.test.js +232 -10
- package/build/services/TestExecutionService.d.ts +12 -1
- package/build/services/TestExecutionService.js +20 -41
- package/build/services/TestGenerationService.d.ts +8 -0
- package/build/services/TestGenerationService.js +62 -17
- package/build/services/TestGenerationService.test.js +67 -1
- package/build/tools/auth/loginTool.js +1 -1
- package/build/tools/auth/logoutTool.js +1 -1
- package/build/tools/code-refactor/codeReuseTool.js +1 -1
- package/build/tools/code-refactor/modularizationTool.js +1 -1
- package/build/tools/executeSkyrampTestTool.js +30 -1
- package/build/tools/fixErrorTool.js +1 -1
- package/build/tools/one-click/oneClickTool.js +1 -1
- package/build/tools/test-management/actionsTool.js +76 -41
- package/build/tools/test-management/actionsTool.test.js +104 -38
- package/build/tools/test-management/analyzeChangesTool.js +102 -4
- package/build/tools/test-management/analyzeChangesTool.test.js +3 -1
- package/build/tools/test-management/analyzeTestHealthTool.js +9 -1
- package/build/tools/test-management/analyzeTestHealthTool.test.js +1 -1
- package/build/tools/trace/startTraceCollectionTool.js +1 -1
- package/build/tools/trace/stopTraceCollectionTool.js +1 -1
- package/build/tools/workspace/initScanWorkspaceTool.js +1 -1
- package/build/tools/workspace/initializeWorkspaceTool.js +1 -1
- package/build/tools/workspace/initializeWorkspaceTool.test.js +1 -1
- package/build/types/RepositoryAnalysis.d.ts +6 -6
- package/build/types/TestAnalysis.d.ts +13 -0
- package/build/utils/dartRouteExtractor.js +8 -30
- package/build/utils/docker.test.js +1 -1
- package/build/utils/fileWalk.d.ts +71 -0
- package/build/utils/fileWalk.js +79 -0
- package/build/utils/fileWalk.test.d.ts +1 -0
- package/build/utils/fileWalk.test.js +252 -0
- package/build/utils/frontendIntegration.js +20 -36
- package/build/utils/frontendSelectors.d.ts +34 -0
- package/build/utils/frontendSelectors.js +124 -0
- package/build/utils/frontendSelectors.test.d.ts +1 -0
- package/build/utils/frontendSelectors.test.js +118 -0
- package/build/utils/importerHop.d.ts +18 -0
- package/build/utils/importerHop.js +48 -3
- package/build/utils/importerHop.test.js +71 -1
- package/build/utils/pythonMountPrefixes.d.ts +25 -0
- package/build/utils/pythonMountPrefixes.js +347 -0
- package/build/utils/pythonMountPrefixes.test.d.ts +1 -0
- package/build/utils/pythonMountPrefixes.test.js +113 -0
- package/build/utils/repoScanner.js +30 -23
- package/build/utils/repoScanner.test.js +98 -0
- package/build/utils/routeParsers.d.ts +7 -1
- package/build/utils/routeParsers.js +32 -18
- package/build/utils/sourceRouteExtractor.js +17 -40
- package/build/utils/trace-parser.js +7 -19
- package/build/utils/versions.d.ts +3 -3
- package/build/utils/versions.js +1 -1
- package/build/utils/walkerCharacterization.test.d.ts +1 -0
- package/build/utils/walkerCharacterization.test.js +233 -0
- package/node_modules/playwright/lib/common/config.js +1 -1
- package/node_modules/playwright/lib/common/configLoader.js +1 -1
- package/node_modules/playwright/lib/common/fixtures.js +1 -1
- package/node_modules/playwright/lib/common/testType.js +1 -1
- package/node_modules/playwright/lib/index.js +2 -2
- package/node_modules/playwright/lib/isomorphic/testTree.js +1 -1
- package/node_modules/playwright/lib/matchers/expect.js +1 -1
- package/node_modules/playwright/lib/mcp/browser/tab.js +1 -1
- package/node_modules/playwright/lib/mcp/browser/tools/navigate.js +1 -1
- package/node_modules/playwright/lib/mcp/browser/tools/tracing.js +1 -1
- package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +7 -0
- package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +2 -1
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +3 -1
- package/node_modules/playwright/lib/reporters/base.js +2 -2
- package/node_modules/playwright/lib/reporters/list.js +1 -1
- package/node_modules/playwright/lib/reporters/teleEmitter.js +1 -1
- package/node_modules/playwright/lib/worker/testInfo.js +2 -2
- package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +23 -126
- package/node_modules/playwright/node_modules/playwright-core/lib/generated/injectedScriptSource.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/generated/pollingRecorderSource.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +2 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{codeMirrorModule-Cqp3cwEJ.js → codeMirrorModule-aszq5EdG.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{defaultSettingsView-CYf9adZh.js → defaultSettingsView-BxS7Jm4s.js} +94 -94
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.d4gkVSou.js → index.D4JTTy4R.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{uiMode.u4_8VnCV.js → uiMode.DaRMQKOI.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/generated/injectedScriptSource.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/generated/pollingRecorderSource.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -1
- package/node_modules/playwright/package.json +1 -1
- package/package.json +3 -3
- package/node_modules/playwright/._ThirdPartyNotices.txt +0 -0
- package/node_modules/playwright/._cli.js +0 -0
- package/node_modules/playwright/._index.d.ts +0 -0
- package/node_modules/playwright/._index.js +0 -0
- package/node_modules/playwright/._index.mjs +0 -0
- package/node_modules/playwright/._jsx-runtime.js +0 -0
- package/node_modules/playwright/._jsx-runtime.mjs +0 -0
- package/node_modules/playwright/._lib +0 -0
- package/node_modules/playwright/._node_modules +0 -0
- package/node_modules/playwright/._package.json +0 -0
- package/node_modules/playwright/._test.d.ts +0 -0
- package/node_modules/playwright/._test.js +0 -0
- package/node_modules/playwright/._test.mjs +0 -0
- package/node_modules/playwright/._types +0 -0
- package/node_modules/playwright/._vitest.config.ts +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._.DS_Store +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._.npmignore +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._README.md +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._ThirdPartyNotices.txt +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._bin +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._browsers.json +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._bundles +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._cli.js +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._index.d.ts +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._index.js +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._index.mjs +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._lib +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._package.json +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._src +0 -0
- package/node_modules/playwright/node_modules/playwright-core/._types +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// Characterization tests for the SIX callers that were migrated onto the shared
|
|
2
|
+
// walkDir/collectFiles primitives. These pin each caller's directory-walking
|
|
3
|
+
// behavior (skip-dirs, dotfile skipping, depth caps, count caps, match
|
|
4
|
+
// predicates, first-match, path normalization, best-effort) through real
|
|
5
|
+
// filesystem fixtures, so the pre-refactor hand-rolled walkers and the
|
|
6
|
+
// post-refactor walkDir-based ones are proven to behave identically.
|
|
7
|
+
//
|
|
8
|
+
// They deliberately exercise the PUBLIC entry points (plus the two
|
|
9
|
+
// TestExecutionService helpers, exported for this purpose) rather than the
|
|
10
|
+
// primitives — the primitives have their own unit tests in fileWalk.test.ts;
|
|
11
|
+
// here we verify each caller wires the primitive up the same way it walked
|
|
12
|
+
// before.
|
|
13
|
+
import { jest } from "@jest/globals";
|
|
14
|
+
import * as fs from "fs";
|
|
15
|
+
import * as os from "os";
|
|
16
|
+
import * as path from "path";
|
|
17
|
+
// TestExecutionService imports dockerode at module load; stub it so importing
|
|
18
|
+
// the module needs no Docker daemon. Everything else uses the REAL fs.
|
|
19
|
+
jest.unstable_mockModule("dockerode", () => ({
|
|
20
|
+
default: jest
|
|
21
|
+
.fn()
|
|
22
|
+
.mockImplementation(() => ({ run: jest.fn(), listImages: jest.fn() })),
|
|
23
|
+
}));
|
|
24
|
+
const { extractDartRoutes } = await import("./dartRouteExtractor.js");
|
|
25
|
+
const { extractSourceRoutes } = await import("./sourceRouteExtractor.js");
|
|
26
|
+
const { discoverTraceFiles, discoverPlaywrightZips } = await import("./trace-parser.js");
|
|
27
|
+
const { checkFrontendFileIntegration } = await import("./frontendIntegration.js");
|
|
28
|
+
const { collectVideoPath, findExcludedPaths } = await import("../services/TestExecutionService.js");
|
|
29
|
+
/** Materialize a file tree under a fresh temp dir; values are file contents. */
|
|
30
|
+
function makeTree(files) {
|
|
31
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "walker-char-"));
|
|
32
|
+
for (const [rel, content] of Object.entries(files)) {
|
|
33
|
+
const abs = path.join(root, rel);
|
|
34
|
+
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
35
|
+
fs.writeFileSync(abs, content);
|
|
36
|
+
}
|
|
37
|
+
return root;
|
|
38
|
+
}
|
|
39
|
+
function relSorted(root, abs) {
|
|
40
|
+
return abs
|
|
41
|
+
.map((p) => path.relative(root, p).replace(/\\/g, "/"))
|
|
42
|
+
.sort();
|
|
43
|
+
}
|
|
44
|
+
// ── dartRouteExtractor.findDartFiles ────────────────────────────────────────
|
|
45
|
+
describe("extractDartRoutes — findDartFiles traversal", () => {
|
|
46
|
+
const GO_ROUTE = (p) => `GoRoute(path: '${p}', builder: (c, s) => Screen());`;
|
|
47
|
+
it("discovers .dart files in normal nested directories", () => {
|
|
48
|
+
const root = makeTree({
|
|
49
|
+
"lib/router.dart": GO_ROUTE("/home"),
|
|
50
|
+
"lib/feature/routes.dart": GO_ROUTE("/feature"),
|
|
51
|
+
});
|
|
52
|
+
expect(extractDartRoutes(root).map((r) => r.path).sort()).toEqual([
|
|
53
|
+
"/feature",
|
|
54
|
+
"/home",
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
it("skips dotfile directories not listed in SKIP_DIRS (startsWith '.')", () => {
|
|
58
|
+
// `.cache` is NOT in dart SKIP_DIRS — only the generic dotfile-dir rule
|
|
59
|
+
// (entry.name.startsWith(".")) keeps it out of the walk.
|
|
60
|
+
const root = makeTree({
|
|
61
|
+
"lib/router.dart": GO_ROUTE("/home"),
|
|
62
|
+
".cache/hidden.dart": GO_ROUTE("/secret"),
|
|
63
|
+
});
|
|
64
|
+
expect(extractDartRoutes(root).map((r) => r.path)).toEqual(["/home"]);
|
|
65
|
+
});
|
|
66
|
+
it("skips SKIP_DIRS entries (build, ios)", () => {
|
|
67
|
+
const root = makeTree({
|
|
68
|
+
"lib/router.dart": GO_ROUTE("/home"),
|
|
69
|
+
"build/generated.dart": GO_ROUTE("/built"),
|
|
70
|
+
"ios/Runner.dart": GO_ROUTE("/ios"),
|
|
71
|
+
});
|
|
72
|
+
expect(extractDartRoutes(root).map((r) => r.path)).toEqual(["/home"]);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
// ── sourceRouteExtractor.findRouterFiles ─────────────────────────────────────
|
|
76
|
+
describe("extractSourceRoutes — findRouterFiles traversal", () => {
|
|
77
|
+
const APP = (p) => `
|
|
78
|
+
import { Routes, Route } from 'react-router-dom';
|
|
79
|
+
export default function App() {
|
|
80
|
+
return (<Routes><Route path="${p}" element={<X />} /></Routes>);
|
|
81
|
+
}
|
|
82
|
+
`;
|
|
83
|
+
it("skips router files inside node_modules and dotfile directories", () => {
|
|
84
|
+
const root = makeTree({
|
|
85
|
+
"src/App.tsx": APP("/ok"),
|
|
86
|
+
"node_modules/pkg/App.tsx": APP("/dep"),
|
|
87
|
+
".backup/App.tsx": APP("/bak"),
|
|
88
|
+
});
|
|
89
|
+
expect(extractSourceRoutes(root).map((r) => r.path)).toEqual(["/ok"]);
|
|
90
|
+
});
|
|
91
|
+
const DEFINE_MODULE = `
|
|
92
|
+
import { defineModule } from '@directus/extensions';
|
|
93
|
+
import Coll from './routes/collection.vue';
|
|
94
|
+
export default defineModule({
|
|
95
|
+
id: 'notes',
|
|
96
|
+
routes: [{ name: 'notes', path: '', component: Coll }],
|
|
97
|
+
});
|
|
98
|
+
`;
|
|
99
|
+
it("treats an index.* file as a router candidate ONLY under a modules/ segment", () => {
|
|
100
|
+
const underModules = makeTree({
|
|
101
|
+
"src/modules/notes/index.ts": DEFINE_MODULE,
|
|
102
|
+
});
|
|
103
|
+
expect(extractSourceRoutes(underModules).map((r) => r.path)).toEqual([
|
|
104
|
+
"/notes",
|
|
105
|
+
]);
|
|
106
|
+
// Same defineModule file, but not under a `modules/` segment: findRouterFiles
|
|
107
|
+
// must not pick `index.ts` as a candidate, so no routes are extracted.
|
|
108
|
+
const notUnderModules = makeTree({
|
|
109
|
+
"src/features/notes/index.ts": DEFINE_MODULE,
|
|
110
|
+
});
|
|
111
|
+
expect(extractSourceRoutes(notUnderModules)).toEqual([]);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
// ── trace-parser.scanDir (via discoverTraceFiles / discoverPlaywrightZips) ───
|
|
115
|
+
describe("discoverTraceFiles / discoverPlaywrightZips — scanDir traversal", () => {
|
|
116
|
+
it("skips SKIP_DIRS while scanning an artifact directory", () => {
|
|
117
|
+
const root = makeTree({
|
|
118
|
+
"tests/trace.json": "{}",
|
|
119
|
+
"tests/node_modules/dep/trace.json": "{}",
|
|
120
|
+
});
|
|
121
|
+
expect(relSorted(root, discoverTraceFiles(root))).toEqual([
|
|
122
|
+
"tests/trace.json",
|
|
123
|
+
]);
|
|
124
|
+
});
|
|
125
|
+
it("finds trace files nested several levels deep inside an artifact dir", () => {
|
|
126
|
+
const root = makeTree({
|
|
127
|
+
".skyramp/a/b/c/playwright_trace.json": "{}",
|
|
128
|
+
});
|
|
129
|
+
expect(relSorted(root, discoverTraceFiles(root))).toEqual([
|
|
130
|
+
".skyramp/a/b/c/playwright_trace.json",
|
|
131
|
+
]);
|
|
132
|
+
});
|
|
133
|
+
it("does not descend into non-artifact dirs beyond the root (depth scoping)", () => {
|
|
134
|
+
const root = makeTree({
|
|
135
|
+
"src/components/trace.json": "{}", // src is not an artifact dir → depth 0 only
|
|
136
|
+
});
|
|
137
|
+
expect(discoverTraceFiles(root)).toEqual([]);
|
|
138
|
+
});
|
|
139
|
+
it("discovers playwright zips only within artifact dirs", () => {
|
|
140
|
+
const root = makeTree({
|
|
141
|
+
"e2e/run_trace.zip": "zip",
|
|
142
|
+
"frontend/public/traces/demo.playwright.zip": "zip",
|
|
143
|
+
});
|
|
144
|
+
expect(relSorted(root, discoverPlaywrightZips(root))).toEqual([
|
|
145
|
+
"e2e/run_trace.zip",
|
|
146
|
+
]);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
// ── frontendIntegration.manualWalkGrep (non-git fallback) ────────────────────
|
|
150
|
+
describe("checkFrontendFileIntegration — manualWalkGrep traversal (non-git)", () => {
|
|
151
|
+
it("finds an importer in a normal directory (real content grep)", () => {
|
|
152
|
+
const repo = makeTree({
|
|
153
|
+
"src/components/Foo.tsx": `export function Foo() { return null; }\n`,
|
|
154
|
+
"src/components/Bar.tsx": `import { Foo } from './Foo';\nexport function Bar() { return Foo(); }\n`,
|
|
155
|
+
});
|
|
156
|
+
const [result] = checkFrontendFileIntegration(repo, [
|
|
157
|
+
"src/components/Foo.tsx",
|
|
158
|
+
]);
|
|
159
|
+
expect(result.integrated).toBe(true);
|
|
160
|
+
expect(result.importers).toEqual(["src/components/Bar.tsx"]);
|
|
161
|
+
});
|
|
162
|
+
it("does not count importers inside EXCLUDED_DIR_PATTERN dirs (node_modules)", () => {
|
|
163
|
+
// Only importer lives under node_modules — the walk must skip that dir, so
|
|
164
|
+
// the component reads as unintegrated.
|
|
165
|
+
const repo = makeTree({
|
|
166
|
+
"src/components/Foo.tsx": `export function Foo() { return null; }\n`,
|
|
167
|
+
"node_modules/pkg/Consumer.tsx": `import { Foo } from '../../src/components/Foo';\n`,
|
|
168
|
+
});
|
|
169
|
+
const [result] = checkFrontendFileIntegration(repo, [
|
|
170
|
+
"src/components/Foo.tsx",
|
|
171
|
+
]);
|
|
172
|
+
expect(result.integrated).toBe(false);
|
|
173
|
+
expect(result.reason).toBe("no-importers");
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
// ── TestExecutionService.collectVideoPath ────────────────────────────────────
|
|
177
|
+
describe("collectVideoPath — first-match recursive walk", () => {
|
|
178
|
+
it("returns undefined for an empty/missing directory", () => {
|
|
179
|
+
const root = makeTree({ "other.txt": "" });
|
|
180
|
+
expect(collectVideoPath(root)).toBeUndefined();
|
|
181
|
+
expect(collectVideoPath("")).toBeUndefined();
|
|
182
|
+
});
|
|
183
|
+
it("finds video.webm nested several levels deep", () => {
|
|
184
|
+
const root = makeTree({ "a/b/c/video.webm": "data" });
|
|
185
|
+
const found = collectVideoPath(root);
|
|
186
|
+
expect(found).toBe(path.join(root, "a", "b", "c", "video.webm"));
|
|
187
|
+
});
|
|
188
|
+
it("returns a single video.webm path when several exist (first match wins)", () => {
|
|
189
|
+
const root = makeTree({
|
|
190
|
+
"x/video.webm": "1",
|
|
191
|
+
"y/video.webm": "2",
|
|
192
|
+
});
|
|
193
|
+
const found = collectVideoPath(root);
|
|
194
|
+
expect(found).toBeDefined();
|
|
195
|
+
expect(path.basename(found ?? "")).toBe("video.webm");
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
// ── TestExecutionService.findExcludedPaths ───────────────────────────────────
|
|
199
|
+
describe("findExcludedPaths — name-list recursive walk", () => {
|
|
200
|
+
it("collects every matching file recursively, as absolute paths", () => {
|
|
201
|
+
const root = makeTree({
|
|
202
|
+
"package.json": "{}",
|
|
203
|
+
"sub/package.json": "{}",
|
|
204
|
+
"sub/deep/package.json": "{}",
|
|
205
|
+
"sub/other.json": "{}",
|
|
206
|
+
});
|
|
207
|
+
const out = findExcludedPaths(root, ["package.json"]);
|
|
208
|
+
expect(relSorted(root, out)).toEqual([
|
|
209
|
+
"package.json",
|
|
210
|
+
"sub/deep/package.json",
|
|
211
|
+
"sub/package.json",
|
|
212
|
+
]);
|
|
213
|
+
});
|
|
214
|
+
it("does not descend into EXCLUDED_MOUNT_ITEMS directories (node_modules)", () => {
|
|
215
|
+
const root = makeTree({
|
|
216
|
+
"package.json": "{}",
|
|
217
|
+
"node_modules/pkg/package.json": "{}",
|
|
218
|
+
});
|
|
219
|
+
const out = findExcludedPaths(root, ["package.json"]);
|
|
220
|
+
expect(relSorted(root, out)).toEqual(["package.json"]);
|
|
221
|
+
});
|
|
222
|
+
it("does not descend into directories whose name is itself excluded", () => {
|
|
223
|
+
// A directory named like an excluded item is skipped for recursion, so a
|
|
224
|
+
// matching file *inside* it is never collected — matching the pre-refactor
|
|
225
|
+
// shouldSkipDir. `keep/config.json` (a real match) is still found.
|
|
226
|
+
const root = makeTree({
|
|
227
|
+
"keep/config.json": "{}",
|
|
228
|
+
"config.json/config.json": "{}", // parent dir excluded → inner file skipped
|
|
229
|
+
});
|
|
230
|
+
const out = findExcludedPaths(root, ["config.json"]);
|
|
231
|
+
expect(relSorted(root, out)).toEqual(["keep/config.json"]);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
@@ -264,7 +264,7 @@ function resolveScript(id, rootDir) {
|
|
|
264
264
|
}
|
|
265
265
|
const defaultGrep = /.*/;
|
|
266
266
|
const defaultReporter = process.env.CI ? "dot" : "list";
|
|
267
|
-
const configInternalSymbol =
|
|
267
|
+
const configInternalSymbol = Symbol("configInternalSymbol");
|
|
268
268
|
function getProjectId(project) {
|
|
269
269
|
return project.__projectId;
|
|
270
270
|
}
|
|
@@ -44,7 +44,7 @@ var import_util = require("../util");
|
|
|
44
44
|
var import_config = require("./config");
|
|
45
45
|
var import_esmLoaderHost = require("./esmLoaderHost");
|
|
46
46
|
var import_compilationCache = require("../transform/compilationCache");
|
|
47
|
-
const kDefineConfigWasUsed =
|
|
47
|
+
const kDefineConfigWasUsed = Symbol("defineConfigWasUsed");
|
|
48
48
|
const defineConfig = (...configs) => {
|
|
49
49
|
let result = configs[0];
|
|
50
50
|
for (let i = 1; i < configs.length; ++i) {
|
|
@@ -194,7 +194,7 @@ Make it top-level in the test file or put in the configuration file.`, location)
|
|
|
194
194
|
this._onLoadError({ message, location });
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
|
-
const signatureSymbol =
|
|
197
|
+
const signatureSymbol = Symbol("signature");
|
|
198
198
|
function formatPotentiallyInternalLocation(location) {
|
|
199
199
|
const isUserFixture = location && (0, import_util.filterStackFile)(location.file);
|
|
200
200
|
return isUserFixture ? (0, import_util.formatLocation)(location) : "<builtin>";
|
|
@@ -30,7 +30,7 @@ var import_test = require("./test");
|
|
|
30
30
|
var import_expect = require("../matchers/expect");
|
|
31
31
|
var import_transform = require("../transform/transform");
|
|
32
32
|
var import_validators = require("./validators");
|
|
33
|
-
const testTypeSymbol =
|
|
33
|
+
const testTypeSymbol = Symbol("testType");
|
|
34
34
|
class TestTypeImpl {
|
|
35
35
|
constructor(fixtures) {
|
|
36
36
|
this.fixtures = fixtures;
|
|
@@ -508,7 +508,7 @@ function resolveClientCerticates(clientCertificates) {
|
|
|
508
508
|
}
|
|
509
509
|
return clientCertificates;
|
|
510
510
|
}
|
|
511
|
-
const kTracingStarted =
|
|
511
|
+
const kTracingStarted = Symbol("kTracingStarted");
|
|
512
512
|
function connectOptionsFromEnv() {
|
|
513
513
|
const wsEndpoint = process.env.PW_TEST_CONNECT_WS_ENDPOINT;
|
|
514
514
|
if (!wsEndpoint)
|
|
@@ -595,7 +595,7 @@ class ArtifactsRecorder {
|
|
|
595
595
|
this._playwright = playwright;
|
|
596
596
|
this._artifactsDir = artifactsDir;
|
|
597
597
|
const screenshotOptions = typeof screenshot === "string" ? void 0 : screenshot;
|
|
598
|
-
this._startedCollectingArtifacts =
|
|
598
|
+
this._startedCollectingArtifacts = Symbol("startedCollectingArtifacts");
|
|
599
599
|
this._screenshotRecorder = new SnapshotRecorder(this, normalizeScreenshotMode(screenshot), "screenshot", "image/png", ".png", async (page, path2) => {
|
|
600
600
|
await page._wrapApiCall(async () => {
|
|
601
601
|
await page.screenshot({ ...screenshotOptions, timeout: 5e3, path: path2, caret: "initial" });
|
|
@@ -320,7 +320,7 @@ function collectTestIds(treeItem) {
|
|
|
320
320
|
visit(treeItem);
|
|
321
321
|
return { testIds, locations };
|
|
322
322
|
}
|
|
323
|
-
const statusEx =
|
|
323
|
+
const statusEx = Symbol("statusEx");
|
|
324
324
|
// Annotate the CommonJS export names for ESM import in node:
|
|
325
325
|
0 && (module.exports = {
|
|
326
326
|
TestTree,
|
|
@@ -34,7 +34,7 @@ var import_testInfo = require("../worker/testInfo");
|
|
|
34
34
|
function createMatchers(actual, info, prefix) {
|
|
35
35
|
return new Proxy((0, import_expectBundle.expect)(actual), new ExpectMetaInfoProxyHandler(actual, info, prefix));
|
|
36
36
|
}
|
|
37
|
-
const userMatchersSymbol =
|
|
37
|
+
const userMatchersSymbol = Symbol("userMatchers");
|
|
38
38
|
function qualifiedMatcherName(qualifier, matcherName) {
|
|
39
39
|
return qualifier.join(":") + "$" + matcherName;
|
|
40
40
|
}
|
|
@@ -432,7 +432,7 @@ function consoleLevelForMessageType(type) {
|
|
|
432
432
|
return "info";
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
|
-
const tabSymbol =
|
|
435
|
+
const tabSymbol = Symbol("tabSymbol");
|
|
436
436
|
// Annotate the CommonJS export names for ESM import in node:
|
|
437
437
|
0 && (module.exports = {
|
|
438
438
|
Tab,
|
|
@@ -28,7 +28,7 @@ const navigate = (0, import_tool.defineTool)({
|
|
|
28
28
|
schema: {
|
|
29
29
|
name: "browser_navigate",
|
|
30
30
|
title: "Navigate to a URL",
|
|
31
|
-
description: "Navigate to a URL. Prefer direct navigation to known URLs over clicking menus or carousels \u2014 menus may open unwanted popups and carousel items cause strict-mode violations. To reload the current page, navigate to the same URL \u2014 the backend converts this to page.reload(). After navigating to a folder where content was just created/edited, always call browser_wait_for with the file name before interacting with it.",
|
|
31
|
+
description: "Navigate to a URL. Prefer direct navigation to known, stable URLs (login page, top-level app sections) over clicking menus or carousels \u2014 menus may open unwanted popups and carousel items cause strict-mode violations. EXCEPTION: to open a specific record/resource whose URL embeds an id (e.g. /workflow/edit/389363994986, /file/12345, /folder/67890), do NOT navigate to that URL directly \u2014 click the item in its list instead, so the recorded trace uses a reusable selector rather than a hardcoded id that breaks reuse on other data. To reload the current page, navigate to the same URL \u2014 the backend converts this to page.reload(). After navigating to a folder where content was just created/edited, always call browser_wait_for with the file name before interacting with it.",
|
|
32
32
|
inputSchema: import_mcpBundle.z.object({
|
|
33
33
|
url: import_mcpBundle.z.string().describe("The URL to navigate to")
|
|
34
34
|
}),
|
|
@@ -223,6 +223,13 @@ async function performClientAction(page, actionInContext) {
|
|
|
223
223
|
await page.goto(action.url, { ...opts, waitUntil: "domcontentloaded" });
|
|
224
224
|
return;
|
|
225
225
|
}
|
|
226
|
+
if (action.name === "evaluate") {
|
|
227
|
+
const expr = typeof action.expression === "string" ? action.expression.trim().replace(/;+$/, "") : "";
|
|
228
|
+
if (expr)
|
|
229
|
+
await page.evaluate(`(${expr}
|
|
230
|
+
)()`);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
226
233
|
if (action.name === "waitForTimeout") {
|
|
227
234
|
await new Promise((resolve) => setTimeout(resolve, action.duration ?? 0));
|
|
228
235
|
return;
|
|
@@ -1977,7 +1977,9 @@ Cell row ${params.row}, column ${params.column} has "${actual}", expected "${par
|
|
|
1977
1977
|
const errParsed = (0, import_response.parseResponse)(result);
|
|
1978
1978
|
const errText = (errParsed?.error ?? errParsed?.text ?? "unknown error").replace(/\s+/g, " ").trim().slice(0, 300);
|
|
1979
1979
|
this._droppedActions.push({ toolName, error: errText });
|
|
1980
|
-
|
|
1980
|
+
process.stderr.write(`[skyramp] Dropped failed action: ${toolName} \u2014 ${errText} (dropped total: ${this._droppedActions.length})
|
|
1981
|
+
`);
|
|
1982
|
+
traceDebug(`Dropped failed action: ${toolName} args=${JSON.stringify(args).slice(0, 200)} \u2014 ${errText}`);
|
|
1981
1983
|
return;
|
|
1982
1984
|
}
|
|
1983
1985
|
const parsed = (0, import_response.parseResponse)(result);
|
|
@@ -52,7 +52,7 @@ var import_utilsBundle = require("playwright-core/lib/utilsBundle");
|
|
|
52
52
|
var import_utils2 = require("playwright-core/lib/utils");
|
|
53
53
|
var import_util = require("../util");
|
|
54
54
|
var import_utilsBundle2 = require("../utilsBundle");
|
|
55
|
-
const kOutputSymbol =
|
|
55
|
+
const kOutputSymbol = Symbol("output");
|
|
56
56
|
const DEFAULT_TTY_WIDTH = 100;
|
|
57
57
|
const DEFAULT_TTY_HEIGHT = 40;
|
|
58
58
|
const originalProcessStdout = process.stdout;
|
|
@@ -402,7 +402,7 @@ function quotePathIfNeeded(path2) {
|
|
|
402
402
|
return `"${path2}"`;
|
|
403
403
|
return path2;
|
|
404
404
|
}
|
|
405
|
-
const kReportedSymbol =
|
|
405
|
+
const kReportedSymbol = Symbol("reported");
|
|
406
406
|
function markErrorsAsReported(result) {
|
|
407
407
|
result[kReportedSymbol] = result.errors.length;
|
|
408
408
|
}
|
|
@@ -249,5 +249,5 @@ class ListReporter extends import_base.TerminalReporter {
|
|
|
249
249
|
this.epilogue(true);
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
|
-
const lastStepOrdinalSymbol =
|
|
252
|
+
const lastStepOrdinalSymbol = Symbol("lastStepOrdinal");
|
|
253
253
|
var list_default = ListReporter;
|
|
@@ -40,7 +40,7 @@ class TeleReporterEmitter {
|
|
|
40
40
|
this._resultKnownErrorCounts = /* @__PURE__ */ new Map();
|
|
41
41
|
// In case there is blob reporter and UI mode, make sure one doesn't override
|
|
42
42
|
// the id assigned by the other.
|
|
43
|
-
this._idSymbol =
|
|
43
|
+
this._idSymbol = Symbol("id");
|
|
44
44
|
this._messageSink = messageSink;
|
|
45
45
|
this._emitterOptions = options;
|
|
46
46
|
}
|
|
@@ -76,7 +76,7 @@ class TestInfoImpl {
|
|
|
76
76
|
this._startTime = (0, import_utils.monotonicTime)();
|
|
77
77
|
this._startWallTime = Date.now();
|
|
78
78
|
this._requireFile = test?._requireFile ?? "";
|
|
79
|
-
this._uniqueSymbol =
|
|
79
|
+
this._uniqueSymbol = Symbol("testInfoUniqueSymbol");
|
|
80
80
|
this._workerParams = workerParams;
|
|
81
81
|
this.repeatEachIndex = workerParams.repeatEachIndex;
|
|
82
82
|
this.retry = retry;
|
|
@@ -525,7 +525,7 @@ class TestSkipError extends Error {
|
|
|
525
525
|
}
|
|
526
526
|
class StepSkipError extends Error {
|
|
527
527
|
}
|
|
528
|
-
const stepSymbol =
|
|
528
|
+
const stepSymbol = Symbol("step");
|
|
529
529
|
// Annotate the CommonJS export names for ESM import in node:
|
|
530
530
|
0 && (module.exports = {
|
|
531
531
|
StepSkipError,
|