@hienlh/ppm 0.18.11 → 0.18.12
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/CHANGELOG.md +5 -0
- package/README.md +81 -23
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/package.json +1 -1
- package/.spike/cdp-client.ts +0 -116
- package/.spike/cleanup-ppm-workspace.mjs +0 -44
- package/.spike/group-protected-probe.ts +0 -21
- package/.spike/pip-eval.ts +0 -17
- package/.spike/pip-page-helpers.js +0 -119
- package/.spike/pip-results-editor-glue.json +0 -105
- package/.spike/pip-results-editor.json +0 -158
- package/.spike/pip-results-input-isolation.json +0 -28
- package/.spike/pip-results-key-probe.json +0 -58
- package/.spike/pip-results-listener-survival.json +0 -98
- package/.spike/pip-results-listeners.json +0 -36
- package/.spike/pip-results-pagehide.json +0 -92
- package/.spike/pip-results-resize.json +0 -104
- package/.spike/pip-results-terminal-debug.json +0 -99
- package/.spike/pip-results-terminal-v2.json +0 -191
- package/.spike/pip-results-terminal.json +0 -220
- package/.spike/pip-results-xterm-trace.json +0 -73
- package/.spike/pip-spike-common.ts +0 -83
- package/.spike/pip-spike-editor-glue.ts +0 -82
- package/.spike/pip-spike-editor.ts +0 -129
- package/.spike/pip-spike-input-isolation.ts +0 -38
- package/.spike/pip-spike-key-probe.ts +0 -34
- package/.spike/pip-spike-listener-survival.ts +0 -54
- package/.spike/pip-spike-listeners.ts +0 -19
- package/.spike/pip-spike-pagehide.ts +0 -59
- package/.spike/pip-spike-resize.ts +0 -42
- package/.spike/pip-spike-setup.ts +0 -63
- package/.spike/pip-spike-terminal-debug.ts +0 -81
- package/.spike/pip-spike-terminal-v2.ts +0 -139
- package/.spike/pip-spike-terminal.ts +0 -169
- package/.spike/pip-spike-xterm-trace.ts +0 -36
- package/.spike/probe-drag-memo-error.mjs +0 -67
- package/.spike/read-dev-db.ts +0 -15
- package/.spike/s.err +0 -63
- package/.spike/scratch-editor-target.ts +0 -7
- package/.spike/smoke-unified-chrome-pip.mjs +0 -353
- package/.spike/tunnel.err +0 -63
- package/.spike/vite-restart.err +0 -663
- package/.spike/w.err +0 -571
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
// Throwaway manual smoke for the unified window chrome + frame-owned PiP.
|
|
2
|
-
// Not part of the test suite; lives in .spike/ (untracked).
|
|
3
|
-
// bun .spike/smoke-unified-chrome-pip.mjs
|
|
4
|
-
import { tmpdir, homedir } from "node:os";
|
|
5
|
-
import { join } from "node:path";
|
|
6
|
-
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
7
|
-
import { Database } from "bun:sqlite";
|
|
8
|
-
import { Cdp, launchChrome, pageInitScript, sleep } from "../tests/e2e/tab-popout-pip-helpers.mjs";
|
|
9
|
-
|
|
10
|
-
const WEB = "http://localhost:5199";
|
|
11
|
-
const API = "http://127.0.0.1:8099";
|
|
12
|
-
const CDP_PORT = 9357;
|
|
13
|
-
const CHROME = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
|
|
14
|
-
const RUN = Date.now().toString(36);
|
|
15
|
-
const PROFILE = join(tmpdir(), `ppm-smoke-${RUN}`);
|
|
16
|
-
const PROJECT_DIR = join(tmpdir(), `ppm-smoke-proj-${RUN}`);
|
|
17
|
-
const PROJECT_NAME = `smoke-pip-${RUN}`;
|
|
18
|
-
|
|
19
|
-
const db = new Database(join(homedir(), ".ppm", "ppm.dev.db"), { readonly: true });
|
|
20
|
-
const TOKEN = JSON.parse(db.query("SELECT value FROM config WHERE key='auth'").get().value).token;
|
|
21
|
-
db.close();
|
|
22
|
-
|
|
23
|
-
const out = [];
|
|
24
|
-
const rec = (name, pass, detail = "") => {
|
|
25
|
-
out.push({ name, pass, detail });
|
|
26
|
-
console.log(`[${pass ? "PASS" : "FAIL"}] ${name}${detail ? " — " + detail : ""}`);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
let cdp, main, mainTargetId, chrome;
|
|
30
|
-
const ev = (e, ms) => cdp.evalJs(main, e, ms);
|
|
31
|
-
const WINDOWS = `(await import('/components/floating-window/window-store.ts')).useWindowStore`;
|
|
32
|
-
const PANELS = `(await import('/stores/panel-store.ts')).usePanelStore`;
|
|
33
|
-
const PIPREG = `(await import('/components/floating-window/window-pip-registry.ts'))`;
|
|
34
|
-
|
|
35
|
-
async function waitFor(expr, ms = 25000, label = expr) {
|
|
36
|
-
const end = Date.now() + ms;
|
|
37
|
-
let last;
|
|
38
|
-
while (Date.now() < end) {
|
|
39
|
-
try {
|
|
40
|
-
last = await ev(`!!(${expr})`, 8000);
|
|
41
|
-
if (last) return true;
|
|
42
|
-
} catch (e) {
|
|
43
|
-
last = e.message;
|
|
44
|
-
}
|
|
45
|
-
await sleep(250);
|
|
46
|
-
}
|
|
47
|
-
throw new Error(`timeout: ${label} (last=${last})`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async function clickSel(selectorExpr, label, sid = main) {
|
|
51
|
-
const json = await cdp.evalJs(
|
|
52
|
-
sid,
|
|
53
|
-
`(() => { const el = ${selectorExpr}; if (!el) return null; const r = el.getBoundingClientRect();
|
|
54
|
-
return JSON.stringify({ x: r.x + r.width / 2, y: r.y + r.height / 2 }); })()`,
|
|
55
|
-
);
|
|
56
|
-
if (!json) throw new Error(`not found: ${label}`);
|
|
57
|
-
const { x, y } = JSON.parse(json);
|
|
58
|
-
await cdp.click(sid, x, y);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const pipBtn = (winLabelIdx = 0) =>
|
|
62
|
-
`[...document.querySelectorAll('[aria-label="Open in picture-in-picture"]')][${winLabelIdx}]`;
|
|
63
|
-
|
|
64
|
-
async function findPipTarget() {
|
|
65
|
-
const t = await cdp.targets();
|
|
66
|
-
return t.find((x) => x.type === "page" && x.openerId === mainTargetId && x.targetId !== mainTargetId) ?? null;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function waitPipTarget(open = true, ms = 15000) {
|
|
70
|
-
const end = Date.now() + ms;
|
|
71
|
-
while (Date.now() < end) {
|
|
72
|
-
await sleep(300);
|
|
73
|
-
const t = await findPipTarget();
|
|
74
|
-
if (open && t) return t;
|
|
75
|
-
if (!open && !t) return null;
|
|
76
|
-
}
|
|
77
|
-
throw new Error(open ? "PiP never opened" : "PiP never closed");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const errors = [];
|
|
81
|
-
|
|
82
|
-
async function api(method, path, body) {
|
|
83
|
-
const r = await fetch(`${API}${path}`, {
|
|
84
|
-
method,
|
|
85
|
-
headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json" },
|
|
86
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
87
|
-
});
|
|
88
|
-
return r.json();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Real double-click: a second press with clickCount 2 is what makes Chrome emit `dblclick`. */
|
|
92
|
-
async function dblclick(sid, x, y) {
|
|
93
|
-
await cdp.send("Input.dispatchMouseEvent", { type: "mouseMoved", x, y }, sid);
|
|
94
|
-
for (const clickCount of [1, 2]) {
|
|
95
|
-
const base = { x, y, button: "left", clickCount };
|
|
96
|
-
await cdp.send("Input.dispatchMouseEvent", { ...base, type: "mousePressed" }, sid);
|
|
97
|
-
await cdp.send("Input.dispatchMouseEvent", { ...base, type: "mouseReleased" }, sid);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/** `use-terminal` hard-codes ws://<host>:8081 for http dev; this dev stack is on 8099. */
|
|
102
|
-
async function retargetTerminalWs(sid, port) {
|
|
103
|
-
await cdp.send("Network.enable", {}, sid).catch(() => {});
|
|
104
|
-
await cdp.send("Network.setCacheDisabled", { cacheDisabled: true }, sid).catch(() => {});
|
|
105
|
-
await cdp.send("Fetch.enable", { patterns: [{ urlPattern: "*/hooks/use-terminal.ts*", requestStage: "Response" }] }, sid);
|
|
106
|
-
cdp.on(async (m) => {
|
|
107
|
-
if (m.method !== "Fetch.requestPaused" || m.sessionId !== sid) return;
|
|
108
|
-
const { requestId } = m.params;
|
|
109
|
-
try {
|
|
110
|
-
const r = await cdp.send("Fetch.getResponseBody", { requestId }, sid);
|
|
111
|
-
const text = (r.base64Encoded ? Buffer.from(r.body, "base64").toString("utf8") : r.body).replace(
|
|
112
|
-
/hostname\}:8081/g,
|
|
113
|
-
`hostname}:${port}`,
|
|
114
|
-
);
|
|
115
|
-
await cdp.send("Fetch.fulfillRequest", {
|
|
116
|
-
requestId,
|
|
117
|
-
responseCode: 200,
|
|
118
|
-
responseHeaders: [
|
|
119
|
-
{ name: "content-type", value: "application/javascript" },
|
|
120
|
-
{ name: "cache-control", value: "no-store" },
|
|
121
|
-
],
|
|
122
|
-
body: Buffer.from(text, "utf8").toString("base64"),
|
|
123
|
-
}, sid);
|
|
124
|
-
} catch {
|
|
125
|
-
await cdp.send("Fetch.continueRequest", { requestId }, sid).catch(() => {});
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async function main_() {
|
|
131
|
-
await mkdir(PROJECT_DIR, { recursive: true });
|
|
132
|
-
await writeFile(join(PROJECT_DIR, "scratch.ts"), "export const scratch = 1;\n", "utf8");
|
|
133
|
-
const created = await api("POST", "/api/projects", { path: PROJECT_DIR, name: PROJECT_NAME });
|
|
134
|
-
if (!created?.ok && !created?.data) throw new Error(`temp project not created: ${JSON.stringify(created)}`);
|
|
135
|
-
console.log(`temp project ${PROJECT_NAME} → ${PROJECT_DIR}`);
|
|
136
|
-
|
|
137
|
-
chrome = await launchChrome({ chromePath: CHROME, cdpPort: CDP_PORT, profileDir: PROFILE, url: "about:blank" });
|
|
138
|
-
cdp = await Cdp.connect(CDP_PORT);
|
|
139
|
-
const end = Date.now() + 20000;
|
|
140
|
-
let page = null;
|
|
141
|
-
while (Date.now() < end && !page) {
|
|
142
|
-
page = (await cdp.targets()).find((t) => t.type === "page");
|
|
143
|
-
if (!page) await sleep(300);
|
|
144
|
-
}
|
|
145
|
-
mainTargetId = page.targetId;
|
|
146
|
-
main = await cdp.attach(mainTargetId);
|
|
147
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, main).catch(() => {});
|
|
148
|
-
await cdp.send("Page.addScriptToEvaluateOnNewDocument", { source: pageInitScript(TOKEN) }, main);
|
|
149
|
-
cdp.on((m) => {
|
|
150
|
-
if (m.method === "Runtime.consoleAPICalled" && m.params?.type === "error") {
|
|
151
|
-
errors.push(JSON.stringify(m.params.args?.map((a) => a.value ?? a.description)).slice(0, 300));
|
|
152
|
-
}
|
|
153
|
-
if (m.method === "Runtime.exceptionThrown") {
|
|
154
|
-
errors.push(String(m.params?.exceptionDetails?.exception?.description ?? "").slice(0, 300));
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
await retargetTerminalWs(main, "8099");
|
|
158
|
-
await cdp.send("Page.navigate", { url: `${WEB}/project/${PROJECT_NAME}` }, main);
|
|
159
|
-
await sleep(4000);
|
|
160
|
-
await waitFor(
|
|
161
|
-
`(await import('/stores/project-store.ts')).useProjectStore.getState().activeProject?.name === ${JSON.stringify(PROJECT_NAME)}`,
|
|
162
|
-
40000,
|
|
163
|
-
"temp project active",
|
|
164
|
-
);
|
|
165
|
-
await waitFor(`${PANELS}.getState().grid.flat().length > 0`, 20000, "grid ready");
|
|
166
|
-
await sleep(1500);
|
|
167
|
-
|
|
168
|
-
// ---- 1. explorer window ----
|
|
169
|
-
const expId = await ev(`${WINDOWS}.getState().open('explorer')`);
|
|
170
|
-
await sleep(2000);
|
|
171
|
-
const expChrome = JSON.parse(await ev(`(async () => {
|
|
172
|
-
const win = document.querySelector('[role="group"][aria-roledescription="window"]');
|
|
173
|
-
const bar = win?.querySelector('[data-skin]');
|
|
174
|
-
return JSON.stringify({
|
|
175
|
-
skin: bar?.getAttribute('data-skin') ?? null,
|
|
176
|
-
pip: !!win?.querySelector('[aria-label="Open in picture-in-picture"]'),
|
|
177
|
-
folderIcon: !!bar?.querySelector('svg'),
|
|
178
|
-
});
|
|
179
|
-
})()`));
|
|
180
|
-
rec("explorer window wears a skinned titlebar with a PiP button", !!expChrome.skin && expChrome.pip, JSON.stringify(expChrome));
|
|
181
|
-
|
|
182
|
-
// ---- 2. explorer PiP: React events alive (folder click navigates) ----
|
|
183
|
-
await clickSel(pipBtn(), "explorer pip button");
|
|
184
|
-
const pipT = await waitPipTarget(true);
|
|
185
|
-
const pipSid = await cdp.attach(pipT.targetId);
|
|
186
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, pipSid).catch(() => {});
|
|
187
|
-
await sleep(1200);
|
|
188
|
-
const inPip = await ev(`!!(${PIPREG}.windowPip(${JSON.stringify(expId)}))`);
|
|
189
|
-
const placeholder = await ev(`document.body.innerText.includes('Playing in picture-in-picture')`);
|
|
190
|
-
rec("explorer body adopted into PiP + frame shows the placeholder", inPip && placeholder, `pip=${inPip} placeholder=${placeholder}`);
|
|
191
|
-
|
|
192
|
-
// Double-click a directory row inside the PiP document (explorer opens folders on dblclick).
|
|
193
|
-
const currentPath = () =>
|
|
194
|
-
ev(`(await import('/components/os-explorer/explorer-store.ts')).useExplorerStore.getState().slices[${JSON.stringify(expId)}]?.path ?? null`);
|
|
195
|
-
const pathBefore = await currentPath();
|
|
196
|
-
const target = await ev(`(async () => {
|
|
197
|
-
const st = (await import('/components/os-explorer/explorer-store.ts')).useExplorerStore.getState();
|
|
198
|
-
const slice = st.slices[${JSON.stringify(expId)}];
|
|
199
|
-
const dir = (slice?.entries ?? []).find(e => e.type === 'directory');
|
|
200
|
-
return dir ? dir.path : null;
|
|
201
|
-
})()`);
|
|
202
|
-
const navigated = await (async () => {
|
|
203
|
-
if (!target) return "no-directory-entry";
|
|
204
|
-
const json = await cdp.evalJs(pipSid, `(() => {
|
|
205
|
-
const el = document.querySelector('[data-testid="explorer-row"][data-path=' + JSON.stringify(${JSON.stringify(target)}) + ']');
|
|
206
|
-
if (!el) return null;
|
|
207
|
-
const r = el.getBoundingClientRect();
|
|
208
|
-
return JSON.stringify({ x: r.x + r.width / 2, y: r.y + r.height / 2 });
|
|
209
|
-
})()`);
|
|
210
|
-
if (!json) return "row-not-in-pip-doc";
|
|
211
|
-
const { x, y } = JSON.parse(json);
|
|
212
|
-
await dblclick(pipSid, x, y);
|
|
213
|
-
await sleep(2500);
|
|
214
|
-
const after = await currentPath();
|
|
215
|
-
return after && after !== pathBefore ? "ok" : `unchanged (${pathBefore} → ${after})`;
|
|
216
|
-
})();
|
|
217
|
-
rec("clicking a folder inside the PiP explorer navigates (React events alive)", navigated === "ok", `${navigated} target=${target}`);
|
|
218
|
-
|
|
219
|
-
// ---- 3. close PiP restores ----
|
|
220
|
-
await clickSel(`document.querySelector('[aria-label="Bring back from picture-in-picture"]')`, "bring back");
|
|
221
|
-
await waitPipTarget(false);
|
|
222
|
-
const restored = await ev(`(async () => {
|
|
223
|
-
const win = document.querySelector('[role="group"][aria-roledescription="window"]');
|
|
224
|
-
return !!win && !document.body.innerText.includes('Playing in picture-in-picture') && win.children.length > 1;
|
|
225
|
-
})()`);
|
|
226
|
-
rec("closing PiP restores the explorer body into its window", restored, `restored=${restored}`);
|
|
227
|
-
await ev(`${WINDOWS}.getState().close(${JSON.stringify(expId)})`);
|
|
228
|
-
await sleep(600);
|
|
229
|
-
|
|
230
|
-
// ---- 4. system monitor window ----
|
|
231
|
-
const sysId = await ev(`${WINDOWS}.getState().open('system-monitor')`);
|
|
232
|
-
await sleep(2500);
|
|
233
|
-
const sysChrome = JSON.parse(await ev(`(async () => {
|
|
234
|
-
const win = document.querySelector('[role="group"][aria-roledescription="window"]');
|
|
235
|
-
const bar = win?.querySelector('[data-skin]');
|
|
236
|
-
return JSON.stringify({ skin: bar?.getAttribute('data-skin') ?? null, pip: !!win?.querySelector('[aria-label="Open in picture-in-picture"]') });
|
|
237
|
-
})()`));
|
|
238
|
-
rec("system monitor window has the same skin + a PiP button", !!sysChrome.skin && sysChrome.pip, JSON.stringify(sysChrome));
|
|
239
|
-
await clickSel(pipBtn(), "sysmon pip button");
|
|
240
|
-
const sysPip = await waitPipTarget(true);
|
|
241
|
-
const sysSid = await cdp.attach(sysPip.targetId);
|
|
242
|
-
await sleep(1500);
|
|
243
|
-
const sysAlive = await cdp.evalJs(sysSid, `document.body.innerText.length > 40`);
|
|
244
|
-
rec("system monitor renders inside PiP", !!sysAlive, `textLen>40=${sysAlive}`);
|
|
245
|
-
await clickSel(`document.querySelector('[aria-label="Bring back from picture-in-picture"]')`, "bring back sysmon");
|
|
246
|
-
await waitPipTarget(false);
|
|
247
|
-
await ev(`${WINDOWS}.getState().close(${JSON.stringify(sysId)})`);
|
|
248
|
-
await sleep(600);
|
|
249
|
-
|
|
250
|
-
// ---- 5. terminal tab pop-out ----
|
|
251
|
-
const TERM = await ev(`${PANELS}.getState().openTab({ type: 'terminal', title: 'Terminal 1', projectId: ${JSON.stringify(PROJECT_NAME)}, closable: true, metadata: { terminalIndex: 1, projectName: ${JSON.stringify(PROJECT_NAME)} } })`);
|
|
252
|
-
const sel = (extra = "") => `document.querySelector('[data-tab-pool-id=' + ${JSON.stringify(JSON.stringify(TERM))} + ']${extra}')`;
|
|
253
|
-
await waitFor(sel(" .xterm"), 40000, "xterm mounted");
|
|
254
|
-
await sleep(2000);
|
|
255
|
-
const winId = await ev(`(async () => {
|
|
256
|
-
const p = ${PANELS}.getState();
|
|
257
|
-
const pid = Object.keys(p.panels).find(id => p.panels[id].tabs.some(t => t.id === ${JSON.stringify(TERM)}));
|
|
258
|
-
return p.popOutTab(${JSON.stringify(TERM)}, pid);
|
|
259
|
-
})()`);
|
|
260
|
-
await sleep(1800);
|
|
261
|
-
const tabChrome = JSON.parse(await ev(`(async () => {
|
|
262
|
-
const win = document.querySelector('[role="group"][aria-roledescription="window"]');
|
|
263
|
-
const bar = win?.querySelector('[data-skin]');
|
|
264
|
-
return JSON.stringify({
|
|
265
|
-
skin: bar?.getAttribute('data-skin') ?? null,
|
|
266
|
-
pip: !!win?.querySelector('[aria-label="Open in picture-in-picture"]'),
|
|
267
|
-
});
|
|
268
|
-
})()`));
|
|
269
|
-
rec(
|
|
270
|
-
"popped-out tab window wears the SAME skin as the explorer",
|
|
271
|
-
tabChrome.skin === expChrome.skin && tabChrome.pip,
|
|
272
|
-
`tab=${JSON.stringify(tabChrome)} explorer=${JSON.stringify(expChrome)}`,
|
|
273
|
-
);
|
|
274
|
-
|
|
275
|
-
await clickSel(pipBtn(), "tab pip button");
|
|
276
|
-
const tPip = await waitPipTarget(true);
|
|
277
|
-
const tSid = await cdp.attach(tPip.targetId);
|
|
278
|
-
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true }, tSid).catch(() => {});
|
|
279
|
-
await sleep(1500);
|
|
280
|
-
const termInPip = await cdp.evalJs(tSid, `!!${sel(" .xterm")}`);
|
|
281
|
-
rec("terminal tab lives in the PiP document", !!termInPip, `xterm=${termInPip}`);
|
|
282
|
-
|
|
283
|
-
// Close the window WHILE in PiP → must restore and re-dock.
|
|
284
|
-
await clickSel(`document.querySelector('[aria-label="Close window"]')`, "close window");
|
|
285
|
-
await waitPipTarget(false);
|
|
286
|
-
await sleep(1500);
|
|
287
|
-
const redocked = JSON.parse(await ev(`(async () => {
|
|
288
|
-
const p = ${PANELS}.getState();
|
|
289
|
-
const pid = Object.keys(p.panels).find(id => p.panels[id].tabs.some(t => t.id === ${JSON.stringify(TERM)}));
|
|
290
|
-
return JSON.stringify({
|
|
291
|
-
panel: pid ?? null,
|
|
292
|
-
gridded: !!pid && p.grid.flat().includes(pid),
|
|
293
|
-
inMainDoc: !!${sel()},
|
|
294
|
-
windows: Object.keys(${WINDOWS}.getState().windows).length,
|
|
295
|
-
});
|
|
296
|
-
})()`));
|
|
297
|
-
rec(
|
|
298
|
-
"closing the window while in PiP restores + re-docks the tab",
|
|
299
|
-
!!redocked.panel && redocked.gridded && redocked.inMainDoc && redocked.windows === 0,
|
|
300
|
-
JSON.stringify(redocked),
|
|
301
|
-
);
|
|
302
|
-
|
|
303
|
-
// ---- 6. the other skin: folder glyph is explorer-only ----
|
|
304
|
-
await ev(`(await import('/stores/settings-store.ts')).useSettingsStore.setState({ explorerSkin: 'windows' })`);
|
|
305
|
-
const winSkinExp = await ev(`${WINDOWS}.getState().open('explorer')`);
|
|
306
|
-
await sleep(1800);
|
|
307
|
-
const winSkinSys = await ev(`${WINDOWS}.getState().open('system-monitor')`);
|
|
308
|
-
await sleep(2200);
|
|
309
|
-
const skinCheck = JSON.parse(await ev(`(async () => {
|
|
310
|
-
const wins =[...document.querySelectorAll('[role="group"][aria-roledescription="window"]')].map(w => {
|
|
311
|
-
const bar = w.querySelector('[data-skin]');
|
|
312
|
-
return {
|
|
313
|
-
label: w.getAttribute('aria-label'),
|
|
314
|
-
skin: bar?.getAttribute('data-skin') ?? null,
|
|
315
|
-
icon: !!bar?.querySelector('div > svg'),
|
|
316
|
-
pip: !!w.querySelector('[aria-label="Open in picture-in-picture"]'),
|
|
317
|
-
};
|
|
318
|
-
});
|
|
319
|
-
return JSON.stringify(wins);
|
|
320
|
-
})()`));
|
|
321
|
-
const sysWin = skinCheck.find((w) => w.label === "System Monitor");
|
|
322
|
-
const expWin = skinCheck.find((w) => w.label !== "System Monitor");
|
|
323
|
-
rec(
|
|
324
|
-
"windows skin: both kinds skinned + PiP, folder glyph only on the explorer",
|
|
325
|
-
skinCheck.every((w) => w.skin === "windows" && w.pip) && expWin?.icon === true && sysWin?.icon === false,
|
|
326
|
-
JSON.stringify(skinCheck),
|
|
327
|
-
);
|
|
328
|
-
await ev(`(async () => { const w = ${WINDOWS}.getState(); w.close(${JSON.stringify(winSkinExp)}); w.close(${JSON.stringify(winSkinSys)}); return 'ok'; })()`);
|
|
329
|
-
await sleep(600);
|
|
330
|
-
|
|
331
|
-
rec("no console errors during the smoke", errors.length === 0, errors.slice(0, 4).join(" || "));
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
try {
|
|
335
|
-
await main_();
|
|
336
|
-
} catch (e) {
|
|
337
|
-
rec("smoke aborted", false, e?.message ?? String(e));
|
|
338
|
-
} finally {
|
|
339
|
-
console.log(`\nPID ${chrome?.pid} — closing`);
|
|
340
|
-
try {
|
|
341
|
-
await cdp?.send("Browser.close");
|
|
342
|
-
} catch {}
|
|
343
|
-
await sleep(1200);
|
|
344
|
-
try {
|
|
345
|
-
if (chrome?.pid) process.kill(chrome.pid);
|
|
346
|
-
} catch {}
|
|
347
|
-
const removed = await api("DELETE", `/api/projects/${PROJECT_NAME}`).catch((e) => ({ error: String(e) }));
|
|
348
|
-
console.log(`temp project removed: ${JSON.stringify(removed)}`);
|
|
349
|
-
await rm(PROJECT_DIR, { recursive: true, force: true }).catch(() => {});
|
|
350
|
-
const failed = out.filter((r) => !r.pass);
|
|
351
|
-
console.log(`\n${out.length - failed.length}/${out.length} passed`);
|
|
352
|
-
process.exit(failed.length ? 1 : 0);
|
|
353
|
-
}
|
package/.spike/tunnel.err
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
2026-09-04T18:56:09Z INF Thank you for trying Cloudflare Tunnel. Doing so, without a Cloudflare account, is a quick way to experiment and try it out. However, be aware that these account-less Tunnels have no uptime guarantee, are subject to the Cloudflare Online Services Terms of Use (https://www.cloudflare.com/website-terms/), and Cloudflare reserves the right to investigate your use of Tunnels for violations of such terms. If you intend to use Tunnels in production you should use a pre-created named tunnel by following: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps
|
|
2
|
-
2026-09-04T18:56:09Z INF Requesting new quick Tunnel on trycloudflare.com...
|
|
3
|
-
2026-09-04T18:56:13Z INF +--------------------------------------------------------------------------------------------+
|
|
4
|
-
2026-09-04T18:56:13Z INF | Your quick Tunnel has been created! Visit it at (it may take some time to be reachable): |
|
|
5
|
-
2026-09-04T18:56:13Z INF | https://cancellation-harold-more-tigers.trycloudflare.com |
|
|
6
|
-
2026-09-04T18:56:13Z INF +--------------------------------------------------------------------------------------------+
|
|
7
|
-
2026-09-04T18:56:13Z INF Cannot determine default configuration path. No file [config.yml config.yaml] in [~/.cloudflared ~/.cloudflare-warp ~/cloudflare-warp]
|
|
8
|
-
2026-09-04T18:56:13Z INF Version 2025.8.1 (Checksum b5d598b00cc3a28cabc5812d9f762819334614bae452db4e7f23eefe7b081556)
|
|
9
|
-
2026-09-04T18:56:13Z INF GOOS: windows, GOVersion: go1.24.2, GoArch: amd64
|
|
10
|
-
2026-09-04T18:56:13Z INF Settings: map[ha-connections:1 no-autoupdate:true protocol:quic url:http://localhost:5173]
|
|
11
|
-
2026-09-04T18:56:13Z INF cloudflared will not automatically update on Windows systems.
|
|
12
|
-
2026-09-04T18:56:13Z INF Generated Connector ID: f47e931b-a8fd-4f00-8ca3-408da700752e
|
|
13
|
-
2026-09-04T18:56:13Z INF Initial protocol quic
|
|
14
|
-
2026-09-04T18:56:13Z INF ICMP proxy will use 192.168.1.35 as source for IPv4
|
|
15
|
-
2026-09-04T18:56:13Z INF ICMP proxy will use 2405:4802:bfda:8c0::7ef in zone Wi-Fi as source for IPv6
|
|
16
|
-
2026-09-04T18:56:13Z ERR Cannot determine default origin certificate path. No file cert.pem in [~/.cloudflared ~/.cloudflare-warp ~/cloudflare-warp]. You need to specify the origin certificate path by specifying the origincert option in the configuration file, or set TUNNEL_ORIGIN_CERT environment variable originCertPath=
|
|
17
|
-
2026-09-04T18:56:13Z INF cloudflared does not support loading the system root certificate pool on Windows. Please use --origin-ca-pool <PATH> to specify the path to the certificate pool
|
|
18
|
-
2026-09-04T18:56:13Z INF ICMP proxy will use 192.168.1.35 as source for IPv4
|
|
19
|
-
2026-09-04T18:56:13Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.200.193
|
|
20
|
-
2026-09-04T18:56:13Z INF ICMP proxy will use 2405:4802:bfda:8c0::7ef in zone Wi-Fi as source for IPv6
|
|
21
|
-
2026-09-04T18:56:13Z INF Starting metrics server on 127.0.0.1:20242/metrics
|
|
22
|
-
2026-09-04T18:56:13Z INF Registered tunnel connection connIndex=0 connection=c174dc70-ed73-417c-9fba-25c88a9c9c0e event=0 ip=198.41.200.193 location=sin11 protocol=quic
|
|
23
|
-
2026-09-04T21:31:09Z ERR failed to run the datagram handler error="timeout: no recent network activity" connIndex=0 event=0 ip=198.41.200.193
|
|
24
|
-
2026-09-04T21:31:09Z ERR failed to accept incoming stream requests error="failed to accept QUIC stream: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.200.193
|
|
25
|
-
2026-09-04T21:31:09Z ERR failed to serve tunnel connection error="datagram manager encountered a failure while serving" connIndex=0 event=0 ip=198.41.200.193
|
|
26
|
-
2026-09-04T21:31:09Z ERR Serve tunnel error error="datagram manager encountered a failure while serving" connIndex=0 event=0 ip=198.41.200.193
|
|
27
|
-
2026-09-04T21:31:09Z INF Retrying connection in up to 1s connIndex=0 event=0 ip=198.41.200.193
|
|
28
|
-
2026-09-04T21:31:10Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.200.193
|
|
29
|
-
2026-09-04T21:31:15Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.200.193
|
|
30
|
-
2026-09-04T21:31:15Z INF Retrying connection in up to 4s connIndex=0 event=0 ip=198.41.200.193
|
|
31
|
-
2026-09-04T21:31:16Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.200.73
|
|
32
|
-
2026-09-04T21:31:19Z ERR Failed to refresh DNS local resolver error="lookup region1.v2.argotunnel.com: i/o timeout"
|
|
33
|
-
2026-09-04T21:31:21Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.200.73
|
|
34
|
-
2026-09-04T21:31:21Z INF Retrying connection in up to 8s connIndex=0 event=0 ip=198.41.200.73
|
|
35
|
-
2026-09-04T21:31:21Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.200.113
|
|
36
|
-
2026-09-04T21:31:26Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.200.113
|
|
37
|
-
2026-09-04T21:31:26Z INF Retrying connection in up to 16s connIndex=0 event=0 ip=198.41.200.113
|
|
38
|
-
2026-09-04T21:31:27Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.192.167
|
|
39
|
-
2026-09-04T21:31:32Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.192.167
|
|
40
|
-
2026-09-04T21:31:32Z INF Retrying connection in up to 32s connIndex=0 event=0 ip=198.41.192.167
|
|
41
|
-
2026-09-04T21:31:53Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.192.107
|
|
42
|
-
2026-09-04T21:31:58Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.192.107
|
|
43
|
-
2026-09-04T21:31:58Z INF Retrying connection in up to 1m4s connIndex=0 event=0 ip=198.41.192.107
|
|
44
|
-
2026-09-04T21:32:23Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.200.73
|
|
45
|
-
2026-09-04T21:32:28Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.200.73
|
|
46
|
-
2026-09-04T21:32:28Z INF Retrying connection in up to 1m4s connIndex=0 event=0 ip=198.41.200.73
|
|
47
|
-
2026-09-04T21:32:48Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.192.77
|
|
48
|
-
2026-09-04T21:32:53Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.192.77
|
|
49
|
-
2026-09-04T21:32:53Z INF Retrying connection in up to 1m4s connIndex=0 event=0 ip=198.41.192.77
|
|
50
|
-
2026-09-04T21:33:24Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.192.37
|
|
51
|
-
2026-09-04T21:33:29Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.192.37
|
|
52
|
-
2026-09-04T21:33:29Z INF Retrying connection in up to 1m4s connIndex=0 event=0 ip=198.41.192.37
|
|
53
|
-
2026-09-04T21:33:30Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.200.193
|
|
54
|
-
2026-09-04T21:33:35Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.200.193
|
|
55
|
-
2026-09-04T21:33:35Z INF Retrying connection in up to 1m4s connIndex=0 event=0 ip=198.41.200.193
|
|
56
|
-
2026-09-04T21:33:45Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.192.7
|
|
57
|
-
2026-09-04T21:33:50Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.192.7
|
|
58
|
-
2026-09-04T21:33:50Z INF Retrying connection in up to 1m4s connIndex=0 event=0 ip=198.41.192.7
|
|
59
|
-
2026-09-04T21:34:00Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.200.53
|
|
60
|
-
2026-09-04T21:34:05Z ERR Failed to dial a quic connection error="failed to dial to edge with quic: timeout: no recent network activity" connIndex=0 event=0 ip=198.41.200.53
|
|
61
|
-
2026-09-04T21:34:05Z INF Retrying connection in up to 1m4s connIndex=0 event=0 ip=198.41.200.53
|
|
62
|
-
2026-09-04T21:34:23Z INF Tunnel connection curve preferences: [X25519MLKEM768 CurveP256] connIndex=0 event=0 ip=198.41.192.47
|
|
63
|
-
2026-09-04T21:34:24Z INF Registered tunnel connection connIndex=0 connection=5bbe5f75-d204-4dca-988b-deb89d022586 event=0 ip=198.41.192.47 location=sin18 protocol=quic
|