@web-auto/camo 0.2.0 → 0.2.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/LICENSE +21 -21
- package/README.md +586 -586
- package/bin/browser-service.mjs +11 -11
- package/bin/camo.mjs +22 -22
- package/package.json +48 -48
- package/scripts/build.mjs +19 -19
- package/scripts/bump-version.mjs +34 -34
- package/scripts/check-file-size.mjs +80 -80
- package/scripts/file-size-policy.json +12 -2
- package/scripts/install.mjs +76 -76
- package/scripts/release.sh +54 -54
- package/src/autoscript/action-providers/index.mjs +6 -6
- package/src/autoscript/impact-engine.mjs +78 -78
- package/src/autoscript/runtime.mjs +1017 -1017
- package/src/autoscript/schema.mjs +376 -376
- package/src/cli.mjs +405 -405
- package/src/commands/attach.mjs +141 -141
- package/src/commands/autoscript.mjs +1011 -1011
- package/src/commands/browser.mjs +1255 -1255
- package/src/commands/container.mjs +401 -401
- package/src/commands/cookies.mjs +69 -69
- package/src/commands/create.mjs +98 -98
- package/src/commands/devtools.mjs +349 -349
- package/src/commands/events.mjs +152 -152
- package/src/commands/highlight-mode.mjs +24 -24
- package/src/commands/init.mjs +68 -68
- package/src/commands/lifecycle.mjs +275 -275
- package/src/commands/mouse.mjs +45 -45
- package/src/commands/profile.mjs +46 -46
- package/src/commands/record.mjs +115 -115
- package/src/commands/system.mjs +14 -14
- package/src/commands/window.mjs +123 -123
- package/src/container/change-notifier.mjs +362 -362
- package/src/container/element-filter.mjs +143 -143
- package/src/container/index.mjs +3 -3
- package/src/container/runtime-core/checkpoint.mjs +209 -209
- package/src/container/runtime-core/index.mjs +21 -21
- package/src/container/runtime-core/operations/index.mjs +774 -774
- package/src/container/runtime-core/operations/selector-scripts.mjs +277 -277
- package/src/container/runtime-core/operations/tab-pool.mjs +746 -746
- package/src/container/runtime-core/operations/viewport.mjs +189 -189
- package/src/container/runtime-core/search.mjs +190 -190
- package/src/container/runtime-core/subscription.mjs +224 -224
- package/src/container/runtime-core/utils.mjs +94 -94
- package/src/container/runtime-core/validation.mjs +127 -127
- package/src/container/runtime-core.mjs +1 -1
- package/src/container/subscription-registry.mjs +459 -459
- package/src/core/actions.mjs +561 -561
- package/src/core/browser.mjs +266 -266
- package/src/core/index.mjs +52 -52
- package/src/core/utils.mjs +91 -91
- package/src/events/daemon-entry.mjs +33 -33
- package/src/events/daemon.mjs +80 -80
- package/src/events/progress-log.mjs +109 -109
- package/src/events/ws-server.mjs +239 -239
- package/src/lib/client.mjs +200 -200
- package/src/lifecycle/cleanup.mjs +83 -83
- package/src/lifecycle/lock.mjs +126 -126
- package/src/lifecycle/session-registry.mjs +279 -279
- package/src/lifecycle/session-view.mjs +76 -76
- package/src/lifecycle/session-watchdog.mjs +281 -281
- package/src/services/browser-service/index.js +671 -671
- package/src/services/browser-service/internal/BrowserSession.input.test.js +389 -389
- package/src/services/browser-service/internal/BrowserSession.js +325 -304
- package/src/services/browser-service/internal/ElementRegistry.js +60 -60
- package/src/services/browser-service/internal/ProfileLock.js +84 -84
- package/src/services/browser-service/internal/SessionManager.js +184 -184
- package/src/services/browser-service/internal/SessionManager.test.js +39 -39
- package/src/services/browser-service/internal/browser-session/cookies.js +144 -144
- package/src/services/browser-service/internal/browser-session/input-ops.js +222 -222
- package/src/services/browser-service/internal/browser-session/input-pipeline.js +144 -144
- package/src/services/browser-service/internal/browser-session/logging.js +46 -46
- package/src/services/browser-service/internal/browser-session/navigation.js +38 -38
- package/src/services/browser-service/internal/browser-session/page-hooks.js +442 -442
- package/src/services/browser-service/internal/browser-session/page-management.js +302 -302
- package/src/services/browser-service/internal/browser-session/page-management.test.js +148 -148
- package/src/services/browser-service/internal/browser-session/recording.js +198 -198
- package/src/services/browser-service/internal/browser-session/runtime-events.js +61 -61
- package/src/services/browser-service/internal/browser-session/session-core.js +84 -84
- package/src/services/browser-service/internal/browser-session/session-state.js +38 -38
- package/src/services/browser-service/internal/browser-session/types.js +14 -14
- package/src/services/browser-service/internal/browser-session/utils.js +95 -95
- package/src/services/browser-service/internal/browser-session/viewport-manager.js +46 -46
- package/src/services/browser-service/internal/browser-session/viewport.js +215 -215
- package/src/services/browser-service/internal/container-matcher.js +851 -851
- package/src/services/browser-service/internal/container-registry.js +182 -182
- package/src/services/browser-service/internal/engine-manager.js +259 -259
- package/src/services/browser-service/internal/fingerprint.js +203 -203
- package/src/services/browser-service/internal/heartbeat.js +137 -137
- package/src/services/browser-service/internal/logging.js +46 -46
- package/src/services/browser-service/internal/page-runtime/runtime.js +1317 -1317
- package/src/services/browser-service/internal/pageRuntime.js +28 -28
- package/src/services/browser-service/internal/runtimeInjector.js +31 -31
- package/src/services/browser-service/internal/service-process-logger.js +140 -140
- package/src/services/browser-service/internal/state-bus.js +45 -45
- package/src/services/browser-service/internal/storage-paths.js +42 -42
- package/src/services/browser-service/internal/ws-server.js +1194 -1194
- package/src/services/browser-service/internal/ws-server.test.js +58 -58
- package/src/services/browser-service/server.mjs +6 -6
- package/src/services/controller/cli-bridge.js +93 -93
- package/src/services/controller/container-index.js +50 -50
- package/src/services/controller/container-storage.js +36 -36
- package/src/services/controller/controller-actions.js +207 -207
- package/src/services/controller/controller.js +1138 -1138
- package/src/services/controller/selectors.js +54 -54
- package/src/services/controller/transport.js +125 -125
- package/src/utils/args.mjs +26 -26
- package/src/utils/browser-service.mjs +544 -544
- package/src/utils/command-log.mjs +64 -64
- package/src/utils/config.mjs +214 -214
- package/src/utils/fingerprint.mjs +181 -181
- package/src/utils/help.mjs +216 -216
- package/src/utils/js-policy.mjs +13 -13
- package/src/utils/ws-client.mjs +30 -30
|
@@ -1,148 +1,148 @@
|
|
|
1
|
-
import test from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { BrowserSessionPageManagement } from './page-management.js';
|
|
4
|
-
|
|
5
|
-
function createPage(label) {
|
|
6
|
-
const page = {
|
|
7
|
-
label,
|
|
8
|
-
closed: false,
|
|
9
|
-
bringToFrontCalls: 0,
|
|
10
|
-
gotoCalls: [],
|
|
11
|
-
waitCalls: [],
|
|
12
|
-
keyboard: {
|
|
13
|
-
presses: [],
|
|
14
|
-
press: async (shortcut) => {
|
|
15
|
-
page.keyboard.presses.push(shortcut);
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
url: () => `https://example.com/${label}`,
|
|
19
|
-
isClosed() {
|
|
20
|
-
return this.closed;
|
|
21
|
-
},
|
|
22
|
-
async bringToFront() {
|
|
23
|
-
this.bringToFrontCalls += 1;
|
|
24
|
-
},
|
|
25
|
-
async waitForLoadState(_state, opts) {
|
|
26
|
-
this.waitCalls.push(Number(opts?.timeout || 0));
|
|
27
|
-
},
|
|
28
|
-
async goto(url) {
|
|
29
|
-
this.gotoCalls.push(url);
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
return page;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function createManagement({ pages, activePage, ctxNewPage, waitForEvent }) {
|
|
36
|
-
let currentActive = activePage;
|
|
37
|
-
const ctx = {
|
|
38
|
-
pages: () => pages,
|
|
39
|
-
newPage: ctxNewPage,
|
|
40
|
-
waitForEvent: waitForEvent || (async () => null),
|
|
41
|
-
};
|
|
42
|
-
const management = new BrowserSessionPageManagement({
|
|
43
|
-
ensureContext: () => ctx,
|
|
44
|
-
getActivePage: () => currentActive,
|
|
45
|
-
getCurrentUrl: () => currentActive?.url?.() || null,
|
|
46
|
-
setActivePage: (page) => {
|
|
47
|
-
currentActive = page ?? null;
|
|
48
|
-
},
|
|
49
|
-
setupPageHooks: () => { },
|
|
50
|
-
ensurePageViewport: async () => { },
|
|
51
|
-
maybeCenterPage: async () => { },
|
|
52
|
-
recordLastKnownUrl: () => { },
|
|
53
|
-
isHeadless: () => false,
|
|
54
|
-
});
|
|
55
|
-
return { management, getActivePage: () => currentActive };
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
test('newPage prefers direct context creation before shortcut retries', async () => {
|
|
59
|
-
const opener = createPage('opener');
|
|
60
|
-
const created = createPage('created');
|
|
61
|
-
const pages = [opener];
|
|
62
|
-
let ctxNewPageCalls = 0;
|
|
63
|
-
const { management, getActivePage } = createManagement({
|
|
64
|
-
pages,
|
|
65
|
-
activePage: opener,
|
|
66
|
-
ctxNewPage: async () => {
|
|
67
|
-
ctxNewPageCalls += 1;
|
|
68
|
-
pages.push(created);
|
|
69
|
-
return created;
|
|
70
|
-
},
|
|
71
|
-
waitForEvent: async () => {
|
|
72
|
-
throw new Error('shortcut path should not run');
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
const result = await management.newPage();
|
|
76
|
-
assert.equal(ctxNewPageCalls, 1);
|
|
77
|
-
assert.equal(opener.keyboard.presses.length, 0);
|
|
78
|
-
assert.equal(result.index, 1);
|
|
79
|
-
assert.equal(result.url, 'https://example.com/created');
|
|
80
|
-
assert.equal(getActivePage(), created);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
test('newPage falls back to shortcut path in strictShortcut mode', async () => {
|
|
84
|
-
const opener = createPage('opener');
|
|
85
|
-
const created = createPage('created');
|
|
86
|
-
const pages = [opener];
|
|
87
|
-
let ctxNewPageCalls = 0;
|
|
88
|
-
const { management, getActivePage } = createManagement({
|
|
89
|
-
pages,
|
|
90
|
-
activePage: opener,
|
|
91
|
-
ctxNewPage: async () => {
|
|
92
|
-
ctxNewPageCalls += 1;
|
|
93
|
-
return created;
|
|
94
|
-
},
|
|
95
|
-
waitForEvent: async () => {
|
|
96
|
-
pages.push(created);
|
|
97
|
-
return created;
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
const result = await management.newPage(undefined, { strictShortcut: true });
|
|
101
|
-
assert.equal(ctxNewPageCalls, 0);
|
|
102
|
-
assert.ok(opener.keyboard.presses.length >= 1);
|
|
103
|
-
assert.equal(result.index, 1);
|
|
104
|
-
assert.equal(getActivePage(), created);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test('listPages keeps track of newly created pages even when context.pages stays stale', async () => {
|
|
108
|
-
const opener = createPage('opener');
|
|
109
|
-
const created = createPage('created');
|
|
110
|
-
const pages = [opener];
|
|
111
|
-
const { management, getActivePage } = createManagement({
|
|
112
|
-
pages,
|
|
113
|
-
activePage: opener,
|
|
114
|
-
ctxNewPage: async () => created,
|
|
115
|
-
waitForEvent: async () => null,
|
|
116
|
-
});
|
|
117
|
-
const result = await management.newPage();
|
|
118
|
-
assert.equal(result.index, 1);
|
|
119
|
-
assert.equal(result.url, 'https://example.com/created');
|
|
120
|
-
assert.equal(getActivePage(), created);
|
|
121
|
-
const listed = management.listPages();
|
|
122
|
-
assert.deepEqual(listed, [
|
|
123
|
-
{ index: 0, url: 'https://example.com/opener', active: false },
|
|
124
|
-
{ index: 1, url: 'https://example.com/created', active: true },
|
|
125
|
-
]);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test('listPages keeps a just-created page visible briefly even if page reports closed immediately', async () => {
|
|
129
|
-
const opener = createPage('opener');
|
|
130
|
-
const created = createPage('created');
|
|
131
|
-
const pages = [opener];
|
|
132
|
-
const { management } = createManagement({
|
|
133
|
-
pages,
|
|
134
|
-
activePage: opener,
|
|
135
|
-
ctxNewPage: async () => {
|
|
136
|
-
created.closed = true;
|
|
137
|
-
return created;
|
|
138
|
-
},
|
|
139
|
-
waitForEvent: async () => null,
|
|
140
|
-
});
|
|
141
|
-
const result = await management.newPage();
|
|
142
|
-
assert.equal(result.index, 1);
|
|
143
|
-
const listed = management.listPages();
|
|
144
|
-
assert.deepEqual(listed, [
|
|
145
|
-
{ index: 0, url: 'https://example.com/opener', active: false },
|
|
146
|
-
{ index: 1, url: 'https://example.com/created', active: true },
|
|
147
|
-
]);
|
|
148
|
-
});
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { BrowserSessionPageManagement } from './page-management.js';
|
|
4
|
+
|
|
5
|
+
function createPage(label) {
|
|
6
|
+
const page = {
|
|
7
|
+
label,
|
|
8
|
+
closed: false,
|
|
9
|
+
bringToFrontCalls: 0,
|
|
10
|
+
gotoCalls: [],
|
|
11
|
+
waitCalls: [],
|
|
12
|
+
keyboard: {
|
|
13
|
+
presses: [],
|
|
14
|
+
press: async (shortcut) => {
|
|
15
|
+
page.keyboard.presses.push(shortcut);
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
url: () => `https://example.com/${label}`,
|
|
19
|
+
isClosed() {
|
|
20
|
+
return this.closed;
|
|
21
|
+
},
|
|
22
|
+
async bringToFront() {
|
|
23
|
+
this.bringToFrontCalls += 1;
|
|
24
|
+
},
|
|
25
|
+
async waitForLoadState(_state, opts) {
|
|
26
|
+
this.waitCalls.push(Number(opts?.timeout || 0));
|
|
27
|
+
},
|
|
28
|
+
async goto(url) {
|
|
29
|
+
this.gotoCalls.push(url);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
return page;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function createManagement({ pages, activePage, ctxNewPage, waitForEvent }) {
|
|
36
|
+
let currentActive = activePage;
|
|
37
|
+
const ctx = {
|
|
38
|
+
pages: () => pages,
|
|
39
|
+
newPage: ctxNewPage,
|
|
40
|
+
waitForEvent: waitForEvent || (async () => null),
|
|
41
|
+
};
|
|
42
|
+
const management = new BrowserSessionPageManagement({
|
|
43
|
+
ensureContext: () => ctx,
|
|
44
|
+
getActivePage: () => currentActive,
|
|
45
|
+
getCurrentUrl: () => currentActive?.url?.() || null,
|
|
46
|
+
setActivePage: (page) => {
|
|
47
|
+
currentActive = page ?? null;
|
|
48
|
+
},
|
|
49
|
+
setupPageHooks: () => { },
|
|
50
|
+
ensurePageViewport: async () => { },
|
|
51
|
+
maybeCenterPage: async () => { },
|
|
52
|
+
recordLastKnownUrl: () => { },
|
|
53
|
+
isHeadless: () => false,
|
|
54
|
+
});
|
|
55
|
+
return { management, getActivePage: () => currentActive };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
test('newPage prefers direct context creation before shortcut retries', async () => {
|
|
59
|
+
const opener = createPage('opener');
|
|
60
|
+
const created = createPage('created');
|
|
61
|
+
const pages = [opener];
|
|
62
|
+
let ctxNewPageCalls = 0;
|
|
63
|
+
const { management, getActivePage } = createManagement({
|
|
64
|
+
pages,
|
|
65
|
+
activePage: opener,
|
|
66
|
+
ctxNewPage: async () => {
|
|
67
|
+
ctxNewPageCalls += 1;
|
|
68
|
+
pages.push(created);
|
|
69
|
+
return created;
|
|
70
|
+
},
|
|
71
|
+
waitForEvent: async () => {
|
|
72
|
+
throw new Error('shortcut path should not run');
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
const result = await management.newPage();
|
|
76
|
+
assert.equal(ctxNewPageCalls, 1);
|
|
77
|
+
assert.equal(opener.keyboard.presses.length, 0);
|
|
78
|
+
assert.equal(result.index, 1);
|
|
79
|
+
assert.equal(result.url, 'https://example.com/created');
|
|
80
|
+
assert.equal(getActivePage(), created);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('newPage falls back to shortcut path in strictShortcut mode', async () => {
|
|
84
|
+
const opener = createPage('opener');
|
|
85
|
+
const created = createPage('created');
|
|
86
|
+
const pages = [opener];
|
|
87
|
+
let ctxNewPageCalls = 0;
|
|
88
|
+
const { management, getActivePage } = createManagement({
|
|
89
|
+
pages,
|
|
90
|
+
activePage: opener,
|
|
91
|
+
ctxNewPage: async () => {
|
|
92
|
+
ctxNewPageCalls += 1;
|
|
93
|
+
return created;
|
|
94
|
+
},
|
|
95
|
+
waitForEvent: async () => {
|
|
96
|
+
pages.push(created);
|
|
97
|
+
return created;
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
const result = await management.newPage(undefined, { strictShortcut: true });
|
|
101
|
+
assert.equal(ctxNewPageCalls, 0);
|
|
102
|
+
assert.ok(opener.keyboard.presses.length >= 1);
|
|
103
|
+
assert.equal(result.index, 1);
|
|
104
|
+
assert.equal(getActivePage(), created);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('listPages keeps track of newly created pages even when context.pages stays stale', async () => {
|
|
108
|
+
const opener = createPage('opener');
|
|
109
|
+
const created = createPage('created');
|
|
110
|
+
const pages = [opener];
|
|
111
|
+
const { management, getActivePage } = createManagement({
|
|
112
|
+
pages,
|
|
113
|
+
activePage: opener,
|
|
114
|
+
ctxNewPage: async () => created,
|
|
115
|
+
waitForEvent: async () => null,
|
|
116
|
+
});
|
|
117
|
+
const result = await management.newPage();
|
|
118
|
+
assert.equal(result.index, 1);
|
|
119
|
+
assert.equal(result.url, 'https://example.com/created');
|
|
120
|
+
assert.equal(getActivePage(), created);
|
|
121
|
+
const listed = management.listPages();
|
|
122
|
+
assert.deepEqual(listed, [
|
|
123
|
+
{ index: 0, url: 'https://example.com/opener', active: false },
|
|
124
|
+
{ index: 1, url: 'https://example.com/created', active: true },
|
|
125
|
+
]);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('listPages keeps a just-created page visible briefly even if page reports closed immediately', async () => {
|
|
129
|
+
const opener = createPage('opener');
|
|
130
|
+
const created = createPage('created');
|
|
131
|
+
const pages = [opener];
|
|
132
|
+
const { management } = createManagement({
|
|
133
|
+
pages,
|
|
134
|
+
activePage: opener,
|
|
135
|
+
ctxNewPage: async () => {
|
|
136
|
+
created.closed = true;
|
|
137
|
+
return created;
|
|
138
|
+
},
|
|
139
|
+
waitForEvent: async () => null,
|
|
140
|
+
});
|
|
141
|
+
const result = await management.newPage();
|
|
142
|
+
assert.equal(result.index, 1);
|
|
143
|
+
const listed = management.listPages();
|
|
144
|
+
assert.deepEqual(listed, [
|
|
145
|
+
{ index: 0, url: 'https://example.com/opener', active: false },
|
|
146
|
+
{ index: 1, url: 'https://example.com/created', active: true },
|
|
147
|
+
]);
|
|
148
|
+
});
|