cdp-tunnel 1.0.13 → 1.0.15
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/cli/index.js +65 -0
- package/extension-new/background.js +6 -1
- package/extension-new/cdp/handler/special.js +47 -27
- package/extension-new/core/state.js +64 -6
- package/extension-new/core/websocket.js +124 -19
- package/package.json +9 -2
- package/server/proxy-server.js +45 -34
- package/.github/workflows/publish.yml +0 -92
- package/.github/workflows/release-assets.yml +0 -50
- package/PUBLISH.md +0 -65
- package/console-test.js +0 -52
- package/docs/README_CN.md +0 -204
- package/docs/config-page-screenshot.png +0 -0
- package/final-console-test.js +0 -105
- package/simple-tab-group-test.js +0 -56
- package/test-cdp-connection.js +0 -85
- package/test-cdp-groups.js +0 -71
- package/test-check-newtab.js +0 -144
- package/test-chrome-native.js +0 -140
- package/test-client-connected.js +0 -99
- package/test-compare-formats.js +0 -88
- package/test-context-features.js +0 -113
- package/test-create-tab.js +0 -113
- package/test-debug-broadcast.js +0 -52
- package/test-debug-targets.js +0 -127
- package/test-expose-newtab.js +0 -164
- package/test-expose-shared.js +0 -189
- package/test-final-logs.js +0 -110
- package/test-fresh-chromium.js +0 -153
- package/test-init-script.js +0 -128
- package/test-keepalive.js +0 -89
- package/test-launch-chromium.js +0 -140
- package/test-launch-vs-connect.js +0 -149
- package/test-listen-events.js +0 -102
- package/test-monitor.js +0 -83
- package/test-multiple-cdp-groups.js +0 -78
- package/test-native.js +0 -96
- package/test-page-connection.js +0 -74
- package/test-playwright-connection.js +0 -45
- package/test-playwright-groups.js +0 -47
- package/test-playwright-pages.js +0 -47
- package/test-playwright-sequence.js +0 -81
- package/test-proper-context.js +0 -129
- package/test-real-final.js +0 -251
- package/test-real-scenario-v2.js +0 -166
- package/test-real-scenario-v3.js +0 -231
- package/test-real-scenario.js +0 -104
- package/test-server-logs.js +0 -98
- package/test-session-id.js +0 -91
- package/test-simple-cdp-groups.js +0 -44
- package/test-simple-context.js +0 -137
- package/test-tab-group-simple.js +0 -58
- package/test-tab-grouping.js +0 -48
- package/test-three-pages.js +0 -192
- package/test-wait-for-page.js +0 -95
- package/test-with-logs.js +0 -118
- package/test-ws-groups.js +0 -59
- package/tests/e2e-auto-test.js +0 -304
- package/tests/iframe-test-page.html +0 -89
- package/tests/playwright-demo.js +0 -45
- package/tests/playwright-interactive.js +0 -261
- package/tests/playwright-multi-demo.js +0 -60
- package/tests/playwright-multi.js +0 -85
- package/tests/playwright-single.js +0 -41
- package/tests/screenshot-config.js +0 -35
- package/tests/test-client.js +0 -89
- package/tests/test-douyin-iframe.js +0 -171
- package/tests/test-iframe-debug.js +0 -204
- package/tests/test-multi-client.js +0 -129
package/test-context-features.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
const { chromium } = require('playwright');
|
|
2
|
-
|
|
3
|
-
async function testContextFeatures(port, label) {
|
|
4
|
-
console.log(`\n${'='.repeat(60)}`);
|
|
5
|
-
console.log(`Testing ${label} (port ${port})`);
|
|
6
|
-
console.log('='.repeat(60));
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
const browser = await chromium.connectOverCDP(`http://localhost:${port}`);
|
|
10
|
-
console.log(`[${label}] Connected successfully!`);
|
|
11
|
-
|
|
12
|
-
const contexts = browser.contexts();
|
|
13
|
-
console.log(`[${label}] Found ${contexts.length} context(s)`);
|
|
14
|
-
|
|
15
|
-
let context;
|
|
16
|
-
if (contexts.length === 0) {
|
|
17
|
-
console.log(`[${label}] Creating new context...`);
|
|
18
|
-
context = await browser.newContext();
|
|
19
|
-
} else {
|
|
20
|
-
context = contexts[0];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
console.log(`[${label}] Testing exposeFunction...`);
|
|
24
|
-
await context.exposeFunction('myCustomFunction', (arg) => {
|
|
25
|
-
console.log(`[${label}] myCustomFunction called with:`, arg);
|
|
26
|
-
return `Hello from ${label}: ${arg}`;
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
console.log(`[${label}] Testing addInitScript...`);
|
|
30
|
-
await context.addInitScript(() => {
|
|
31
|
-
window.myInitScript = 'This is from addInitScript!';
|
|
32
|
-
console.log('Init script executed!');
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
console.log(`[${label}] Creating first page...`);
|
|
36
|
-
const page1 = await context.newPage();
|
|
37
|
-
await page1.goto('https://www.example.com');
|
|
38
|
-
|
|
39
|
-
console.log(`[${label}] Testing in first page...`);
|
|
40
|
-
const result1 = await page1.evaluate(async () => {
|
|
41
|
-
const funcResult = await window.myCustomFunction('test1');
|
|
42
|
-
const initResult = window.myInitScript;
|
|
43
|
-
return { funcResult, initResult };
|
|
44
|
-
});
|
|
45
|
-
console.log(`[${label}] First page result:`, result1);
|
|
46
|
-
|
|
47
|
-
console.log(`[${label}] Creating second page (new tab)...`);
|
|
48
|
-
const page2 = await context.newPage();
|
|
49
|
-
await page2.goto('https://www.example.com');
|
|
50
|
-
|
|
51
|
-
console.log(`[${label}] Testing in second page (should persist)...`);
|
|
52
|
-
const result2 = await page2.evaluate(async () => {
|
|
53
|
-
const funcResult = await window.myCustomFunction('test2');
|
|
54
|
-
const initResult = window.myInitScript;
|
|
55
|
-
return { funcResult, initResult };
|
|
56
|
-
});
|
|
57
|
-
console.log(`[${label}] Second page result:`, result2);
|
|
58
|
-
|
|
59
|
-
console.log(`[${label}] Switching back to first page...`);
|
|
60
|
-
const result1Again = await page1.evaluate(async () => {
|
|
61
|
-
const funcResult = await window.myCustomFunction('test1-again');
|
|
62
|
-
const initResult = window.myInitScript;
|
|
63
|
-
return { funcResult, initResult };
|
|
64
|
-
});
|
|
65
|
-
console.log(`[${label}] First page (after switch) result:`, result1Again);
|
|
66
|
-
|
|
67
|
-
console.log(`[${label}] Creating third page...`);
|
|
68
|
-
const page3 = await context.newPage();
|
|
69
|
-
await page3.goto('https://www.example.com');
|
|
70
|
-
|
|
71
|
-
console.log(`[${label}] Testing in third page...`);
|
|
72
|
-
const result3 = await page3.evaluate(async () => {
|
|
73
|
-
const funcResult = await window.myCustomFunction('test3');
|
|
74
|
-
const initResult = window.myInitScript;
|
|
75
|
-
return { funcResult, initResult };
|
|
76
|
-
});
|
|
77
|
-
console.log(`[${label}] Third page result:`, result3);
|
|
78
|
-
|
|
79
|
-
console.log(`[${label}] ✓ All tests passed!`);
|
|
80
|
-
|
|
81
|
-
await browser.close();
|
|
82
|
-
|
|
83
|
-
return true;
|
|
84
|
-
} catch (error) {
|
|
85
|
-
console.error(`[${label}] ✗ Error:`, error.message);
|
|
86
|
-
console.error(`[${label}] Stack:`, error.stack);
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async function main() {
|
|
92
|
-
console.log('Testing Context-level features persistence across tabs');
|
|
93
|
-
console.log('This tests if exposeFunction and addInitScript persist across different tabs\n');
|
|
94
|
-
|
|
95
|
-
const nativeResult = await testContextFeatures(9333, 'Native CDP');
|
|
96
|
-
const tunnelResult = await testContextFeatures(9221, 'CDP Tunnel');
|
|
97
|
-
|
|
98
|
-
console.log('\n' + '='.repeat(60));
|
|
99
|
-
console.log('COMPARISON RESULTS');
|
|
100
|
-
console.log('='.repeat(60));
|
|
101
|
-
console.log(`Native CDP (port 9333): ${nativeResult ? '✓ PASS' : '✗ FAIL'}`);
|
|
102
|
-
console.log(`CDP Tunnel (port 9221): ${tunnelResult ? '✓ PASS' : '✗ FAIL'}`);
|
|
103
|
-
|
|
104
|
-
if (nativeResult && tunnelResult) {
|
|
105
|
-
console.log('\n✓ Both implementations behave identically!');
|
|
106
|
-
} else if (nativeResult && !tunnelResult) {
|
|
107
|
-
console.log('\n✗ CDP Tunnel has issues with Context-level features!');
|
|
108
|
-
} else {
|
|
109
|
-
console.log('\n✗ Native CDP has issues (unexpected)!');
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
main();
|
package/test-create-tab.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
const WebSocket = require('ws');
|
|
2
|
-
const http = require('http');
|
|
3
|
-
|
|
4
|
-
async function test() {
|
|
5
|
-
// 创建本地服务器
|
|
6
|
-
const html = `
|
|
7
|
-
<!DOCTYPE html>
|
|
8
|
-
<html>
|
|
9
|
-
<head><title>Test</title></head>
|
|
10
|
-
<body>
|
|
11
|
-
<h1>Test Page</h1>
|
|
12
|
-
<a href="about:blank" target="_blank" id="link">Open New Tab</a>
|
|
13
|
-
</body>
|
|
14
|
-
</html>
|
|
15
|
-
`;
|
|
16
|
-
|
|
17
|
-
const server = http.createServer((req, res) => {
|
|
18
|
-
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
19
|
-
res.end(html);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
await new Promise(r => server.listen(9999, r));
|
|
23
|
-
console.log('Server: http://localhost:9999');
|
|
24
|
-
|
|
25
|
-
// 连接到 CDP Tunnel
|
|
26
|
-
console.log('\nConnecting to CDP Tunnel...');
|
|
27
|
-
const ws = new WebSocket('ws://localhost:9221/client');
|
|
28
|
-
|
|
29
|
-
let targetCreatedCount = 0;
|
|
30
|
-
|
|
31
|
-
ws.on('open', () => {
|
|
32
|
-
console.log('Connected!');
|
|
33
|
-
|
|
34
|
-
// 1. 获取所有 targets
|
|
35
|
-
ws.send(JSON.stringify({
|
|
36
|
-
id: 1,
|
|
37
|
-
method: 'Target.getTargets',
|
|
38
|
-
params: {}
|
|
39
|
-
}));
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
ws.on('message', (data) => {
|
|
43
|
-
try {
|
|
44
|
-
const msg = JSON.parse(data.toString());
|
|
45
|
-
|
|
46
|
-
// 打印所有 Target 相关事件
|
|
47
|
-
if (msg.method && msg.method.startsWith('Target.')) {
|
|
48
|
-
console.log('[EVENT]', msg.method);
|
|
49
|
-
if (msg.method === 'Target.targetCreated') {
|
|
50
|
-
targetCreatedCount++;
|
|
51
|
-
console.log(' targetId:', msg.params?.targetInfo?.targetId?.substring(0, 8));
|
|
52
|
-
console.log(' type:', msg.params?.targetInfo?.type);
|
|
53
|
-
console.log(' url:', msg.params?.targetInfo?.url?.substring(0, 50));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// 收到 getTargets 响应后,启用 discover
|
|
58
|
-
if (msg.id === 1 && msg.result) {
|
|
59
|
-
console.log('\nGot', msg.result.targetInfos.length, 'targets');
|
|
60
|
-
|
|
61
|
-
// 2. 启用 Target.setDiscoverTargets
|
|
62
|
-
ws.send(JSON.stringify({
|
|
63
|
-
id: 2,
|
|
64
|
-
method: 'Target.setDiscoverTargets',
|
|
65
|
-
params: { discover: true }
|
|
66
|
-
}));
|
|
67
|
-
console.log('Sent Target.setDiscoverTargets');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// 收到 setDiscoverTargets 响应后,创建新 target
|
|
71
|
-
if (msg.id === 2 && msg.result !== undefined) {
|
|
72
|
-
console.log('\nDiscover enabled, creating new target...');
|
|
73
|
-
|
|
74
|
-
// 3. 创建新 target
|
|
75
|
-
setTimeout(() => {
|
|
76
|
-
ws.send(JSON.stringify({
|
|
77
|
-
id: 3,
|
|
78
|
-
method: 'Target.createTarget',
|
|
79
|
-
params: { url: 'http://localhost:9999' }
|
|
80
|
-
}));
|
|
81
|
-
console.log('Sent Target.createTarget');
|
|
82
|
-
}, 1000);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// 收到 createTarget 响应
|
|
86
|
-
if (msg.id === 3 && msg.result) {
|
|
87
|
-
console.log('\nNew target created:', msg.result.targetId?.substring(0, 8));
|
|
88
|
-
|
|
89
|
-
// 等待一段时间,看看是否收到 targetCreated 事件
|
|
90
|
-
setTimeout(() => {
|
|
91
|
-
console.log('\n=== RESULTS ===');
|
|
92
|
-
console.log('Target.targetCreated events received:', targetCreatedCount);
|
|
93
|
-
ws.close();
|
|
94
|
-
server.close();
|
|
95
|
-
}, 3000);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
} catch (e) {
|
|
99
|
-
console.log('[ERROR]', e.message);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
ws.on('close', () => {
|
|
104
|
-
console.log('Connection closed');
|
|
105
|
-
process.exit(0);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
ws.on('error', (err) => {
|
|
109
|
-
console.error('Error:', err.message);
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
test();
|
package/test-debug-broadcast.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
const WebSocket = require('ws');
|
|
2
|
-
|
|
3
|
-
// 连接到代理服务器
|
|
4
|
-
const ws = new WebSocket('ws://localhost:9221/client');
|
|
5
|
-
|
|
6
|
-
ws.on('open', () => {
|
|
7
|
-
console.log('[TEST] Connected to proxy server');
|
|
8
|
-
|
|
9
|
-
// 启用 Target 域来接收 targetCreated 事件
|
|
10
|
-
ws.send(JSON.stringify({
|
|
11
|
-
id: 1,
|
|
12
|
-
method: 'Target.setDiscoverTargets',
|
|
13
|
-
params: { discover: true }
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
|
-
console.log('[TEST] Sent Target.setDiscoverTargets');
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
ws.on('message', (data) => {
|
|
20
|
-
try {
|
|
21
|
-
const msg = JSON.parse(data.toString());
|
|
22
|
-
|
|
23
|
-
// 只打印 Target 相关的事件
|
|
24
|
-
if (msg.method && msg.method.startsWith('Target.')) {
|
|
25
|
-
console.log('[EVENT]', msg.method, {
|
|
26
|
-
targetId: msg.params?.targetInfo?.targetId?.substring(0, 8),
|
|
27
|
-
type: msg.params?.targetInfo?.type,
|
|
28
|
-
url: msg.params?.targetInfo?.url?.substring(0, 50)
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
} catch (e) {
|
|
32
|
-
console.log('[RAW]', data.toString().substring(0, 100));
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
ws.on('close', (code, reason) => {
|
|
37
|
-
console.log('[TEST] Connection closed:', code, reason.toString());
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
ws.on('error', (err) => {
|
|
41
|
-
console.error('[TEST] Error:', err.message);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// 30秒后关闭
|
|
45
|
-
setTimeout(() => {
|
|
46
|
-
console.log('[TEST] Closing connection...');
|
|
47
|
-
ws.close();
|
|
48
|
-
process.exit(0);
|
|
49
|
-
}, 30000);
|
|
50
|
-
|
|
51
|
-
console.log('[TEST] Waiting for Target events...');
|
|
52
|
-
console.log('[TEST] Please open a new tab manually in Chrome');
|
package/test-debug-targets.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
const { chromium } = require('playwright');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
|
|
5
|
-
let serverPort = 9300;
|
|
6
|
-
|
|
7
|
-
async function testWithDebugging(label, port) {
|
|
8
|
-
serverPort++;
|
|
9
|
-
const currentPort = serverPort;
|
|
10
|
-
|
|
11
|
-
console.log(`\n${'='.repeat(60)}`);
|
|
12
|
-
console.log(`Testing ${label} (port ${port})`);
|
|
13
|
-
console.log('='.repeat(60));
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
const htmlContent1 = `
|
|
17
|
-
<!DOCTYPE html>
|
|
18
|
-
<html>
|
|
19
|
-
<head><title>Page 1</title></head>
|
|
20
|
-
<body>
|
|
21
|
-
<h1>Page 1</h1>
|
|
22
|
-
<a href="page2.html" target="_blank" id="link1">Open New Tab</a>
|
|
23
|
-
</body>
|
|
24
|
-
</html>
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
const htmlContent2 = `
|
|
28
|
-
<!DOCTYPE html>
|
|
29
|
-
<html>
|
|
30
|
-
<head><title>Page 2</title></head>
|
|
31
|
-
<body>
|
|
32
|
-
<h1>Page 2 - New Tab</h1>
|
|
33
|
-
</body>
|
|
34
|
-
</html>
|
|
35
|
-
`;
|
|
36
|
-
|
|
37
|
-
const serverDir = '/tmp/test-debug';
|
|
38
|
-
if (!fs.existsSync(serverDir)) {
|
|
39
|
-
fs.mkdirSync(serverDir, { recursive: true });
|
|
40
|
-
}
|
|
41
|
-
fs.writeFileSync(path.join(serverDir, 'page1.html'), htmlContent1);
|
|
42
|
-
fs.writeFileSync(path.join(serverDir, 'page2.html'), htmlContent2);
|
|
43
|
-
|
|
44
|
-
const http = require('http');
|
|
45
|
-
const server = http.createServer((req, res) => {
|
|
46
|
-
let filePath = path.join(serverDir, req.url === '/' ? 'page1.html' : req.url);
|
|
47
|
-
if (fs.existsSync(filePath)) {
|
|
48
|
-
const content = fs.readFileSync(filePath);
|
|
49
|
-
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
50
|
-
res.end(content);
|
|
51
|
-
} else {
|
|
52
|
-
res.writeHead(404);
|
|
53
|
-
res.end('Not found');
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
await new Promise(resolve => server.listen(currentPort, resolve));
|
|
58
|
-
console.log(`[${label}] Server on port ${currentPort}`);
|
|
59
|
-
|
|
60
|
-
console.log(`[${label}] Connecting to browser...`);
|
|
61
|
-
const browser = await chromium.connectOverCDP(`http://localhost:${port}`);
|
|
62
|
-
console.log(`[${label}] Connected!`);
|
|
63
|
-
|
|
64
|
-
console.log(`[${label}] Getting all targets via CDP...`);
|
|
65
|
-
const session = await browser.newBrowserCDPSession();
|
|
66
|
-
const targets = await session.send('Target.getTargets');
|
|
67
|
-
|
|
68
|
-
console.log(`[${label}] Current targets:`);
|
|
69
|
-
const pageTargets = targets.targetInfos.filter(t => t.type === 'page');
|
|
70
|
-
pageTargets.forEach(t => {
|
|
71
|
-
console.log(` - ${t.targetId}: ${t.url} (attached: ${t.attached})`);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
console.log(`[${label}] Creating context...`);
|
|
75
|
-
const context = await browser.newContext();
|
|
76
|
-
|
|
77
|
-
console.log(`[${label}] Creating first page...`);
|
|
78
|
-
const page1 = await context.newPage();
|
|
79
|
-
await page1.goto(`http://localhost:${currentPort}/page1.html`, { waitUntil: 'domcontentloaded' });
|
|
80
|
-
|
|
81
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
82
|
-
|
|
83
|
-
console.log(`[${label}] Checking targets after creating first page...`);
|
|
84
|
-
const targets2 = await session.send('Target.getTargets');
|
|
85
|
-
const pageTargets2 = targets2.targetInfos.filter(t => t.type === 'page');
|
|
86
|
-
pageTargets2.forEach(t => {
|
|
87
|
-
console.log(` - ${t.targetId}: ${t.url} (attached: ${t.attached})`);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
console.log(`[${label}] Clicking link...`);
|
|
91
|
-
await page1.click('#link1');
|
|
92
|
-
|
|
93
|
-
console.log(`[${label}] Waiting 5 seconds...`);
|
|
94
|
-
await new Promise(r => setTimeout(r, 5000));
|
|
95
|
-
|
|
96
|
-
console.log(`[${label}] Checking targets after clicking link...`);
|
|
97
|
-
const targets3 = await session.send('Target.getTargets');
|
|
98
|
-
const pageTargets3 = targets3.targetInfos.filter(t => t.type === 'page');
|
|
99
|
-
pageTargets3.forEach(t => {
|
|
100
|
-
console.log(` - ${t.targetId}: ${t.url} (attached: ${t.attached})`);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
console.log(`[${label}] Checking context pages...`);
|
|
104
|
-
const allPages = context.pages();
|
|
105
|
-
console.log(`[${label}] Total pages in context: ${allPages.length}`);
|
|
106
|
-
allPages.forEach((p, i) => {
|
|
107
|
-
console.log(` Page ${i}: ${p.url()}`);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
server.close();
|
|
111
|
-
await browser.close();
|
|
112
|
-
|
|
113
|
-
} catch (error) {
|
|
114
|
-
console.error(`[${label}] Error:`, error.message);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async function main() {
|
|
119
|
-
console.log('=== CDP Target Debugging Test ===\n');
|
|
120
|
-
|
|
121
|
-
console.log('### Test with CDP Tunnel (port 9221) ###');
|
|
122
|
-
await testWithDebugging('CDP Tunnel', 9221);
|
|
123
|
-
|
|
124
|
-
process.exit(0);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
main();
|
package/test-expose-newtab.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
const { chromium } = require('playwright');
|
|
2
|
-
const { spawn } = require('child_process');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
let serverPort = 8800;
|
|
7
|
-
|
|
8
|
-
async function testExposeFunctionNewTab(port, label) {
|
|
9
|
-
serverPort++;
|
|
10
|
-
const currentPort = serverPort;
|
|
11
|
-
|
|
12
|
-
console.log(`\n${'='.repeat(60)}`);
|
|
13
|
-
console.log(`Testing ${label} (port ${port})`);
|
|
14
|
-
console.log('='.repeat(60));
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
const sharedState = { counter: 0 };
|
|
18
|
-
|
|
19
|
-
const htmlContent1 = `
|
|
20
|
-
<!DOCTYPE html>
|
|
21
|
-
<html>
|
|
22
|
-
<head><title>Page 1</title></head>
|
|
23
|
-
<body>
|
|
24
|
-
<h1>Page 1</h1>
|
|
25
|
-
<a href="page2.html" target="_blank" id="link1">Open New Tab</a>
|
|
26
|
-
<button id="btn" onclick="window.getCounter().then(r => alert('Counter: ' + r))">Get Counter</button>
|
|
27
|
-
</body>
|
|
28
|
-
</html>
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
const htmlContent2 = `
|
|
32
|
-
<!DOCTYPE html>
|
|
33
|
-
<html>
|
|
34
|
-
<head><title>Page 2</title></head>
|
|
35
|
-
<body>
|
|
36
|
-
<h1>Page 2 - New Tab</h1>
|
|
37
|
-
<button id="btn" onclick="window.getCounter().then(r => alert('Counter: ' + r))">Get Counter</button>
|
|
38
|
-
</body>
|
|
39
|
-
</html>
|
|
40
|
-
`;
|
|
41
|
-
|
|
42
|
-
const serverDir = '/tmp/test-expose-newtab';
|
|
43
|
-
if (!fs.existsSync(serverDir)) {
|
|
44
|
-
fs.mkdirSync(serverDir, { recursive: true });
|
|
45
|
-
}
|
|
46
|
-
fs.writeFileSync(path.join(serverDir, 'page1.html'), htmlContent1);
|
|
47
|
-
fs.writeFileSync(path.join(serverDir, 'page2.html'), htmlContent2);
|
|
48
|
-
|
|
49
|
-
const http = require('http');
|
|
50
|
-
const server = http.createServer((req, res) => {
|
|
51
|
-
let filePath = path.join(serverDir, req.url === '/' ? 'page1.html' : req.url);
|
|
52
|
-
if (fs.existsSync(filePath)) {
|
|
53
|
-
const content = fs.readFileSync(filePath);
|
|
54
|
-
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
55
|
-
res.end(content);
|
|
56
|
-
} else {
|
|
57
|
-
res.writeHead(404);
|
|
58
|
-
res.end('Not found');
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
await new Promise(resolve => server.listen(currentPort, resolve));
|
|
63
|
-
console.log(`[${label}] Test server started on port ${currentPort}`);
|
|
64
|
-
|
|
65
|
-
const browser = await chromium.connectOverCDP(`http://localhost:${port}`);
|
|
66
|
-
console.log(`[${label}] Connected successfully!`);
|
|
67
|
-
|
|
68
|
-
console.log(`[${label}] Creating new context...`);
|
|
69
|
-
const context = await browser.newContext();
|
|
70
|
-
|
|
71
|
-
console.log(`[${label}] exposeFunction getCounter...`);
|
|
72
|
-
await context.exposeFunction('getCounter', () => {
|
|
73
|
-
sharedState.counter += 1;
|
|
74
|
-
console.log(`[${label}] getCounter called, counter: ${sharedState.counter}`);
|
|
75
|
-
return sharedState.counter;
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
console.log(`[${label}] Creating first page...`);
|
|
79
|
-
const page1 = await context.newPage();
|
|
80
|
-
await page1.goto(`http://localhost:${currentPort}/page1.html`, { waitUntil: 'domcontentloaded' });
|
|
81
|
-
|
|
82
|
-
console.log(`[${label}] Calling getCounter in first page...`);
|
|
83
|
-
const r1 = await page1.evaluate(() => window.getCounter());
|
|
84
|
-
console.log(`[${label}] First page result: ${r1}`);
|
|
85
|
-
|
|
86
|
-
console.log(`[${label}] Clicking link to open new tab...`);
|
|
87
|
-
const [page2] = await Promise.all([
|
|
88
|
-
context.waitForEvent('page', { timeout: 10000 }),
|
|
89
|
-
page1.click('#link1')
|
|
90
|
-
]);
|
|
91
|
-
|
|
92
|
-
console.log(`[${label}] Waiting for new tab...`);
|
|
93
|
-
await page2.waitForLoadState('domcontentloaded');
|
|
94
|
-
console.log(`[${label}] New tab URL: ${page2.url()}`);
|
|
95
|
-
|
|
96
|
-
console.log(`[${label}] Calling getCounter in new tab...`);
|
|
97
|
-
const r2 = await page2.evaluate(() => window.getCounter());
|
|
98
|
-
console.log(`[${label}] New tab result: ${r2}`);
|
|
99
|
-
|
|
100
|
-
console.log(`[${label}] First page again...`);
|
|
101
|
-
const r1a = await page1.evaluate(() => window.getCounter());
|
|
102
|
-
console.log(`[${label}] First page again result: ${r1a}`);
|
|
103
|
-
|
|
104
|
-
console.log(`[${label}] New tab again...`);
|
|
105
|
-
const r2a = await page2.evaluate(() => window.getCounter());
|
|
106
|
-
console.log(`[${label}] New tab again result: ${r2a}`);
|
|
107
|
-
|
|
108
|
-
const success = r1 === 1 && r2 === 2 && r1a === 3 && r2a === 4;
|
|
109
|
-
|
|
110
|
-
server.close();
|
|
111
|
-
|
|
112
|
-
if (success) {
|
|
113
|
-
console.log(`[${label}] ✓ PASS! Counter: 1 -> 2 -> 3 -> 4`);
|
|
114
|
-
} else {
|
|
115
|
-
console.log(`[${label}] ✗ FAIL! Expected: 1,2,3,4 Got: ${r1},${r2},${r1a},${r2a}`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
await browser.close();
|
|
119
|
-
return success;
|
|
120
|
-
|
|
121
|
-
} catch (error) {
|
|
122
|
-
console.error(`[${label}] ✗ Error:`, error.message);
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async function main() {
|
|
128
|
-
console.log('Testing: Click link -> New tab -> getCounter (shared state)');
|
|
129
|
-
console.log('Expected: 1 -> 2 -> 3 -> 4\n');
|
|
130
|
-
|
|
131
|
-
console.log('Step 1: Starting fresh Chromium on port 9230...');
|
|
132
|
-
const chromiumProcess = spawn('/Applications/Chromium.app/Contents/MacOS/Chromium', [
|
|
133
|
-
'--remote-debugging-port=9230',
|
|
134
|
-
'--user-data-dir=/tmp/chromium-test-newtab',
|
|
135
|
-
'--no-first-run',
|
|
136
|
-
'--no-default-browser-check'
|
|
137
|
-
], { detached: true, stdio: 'ignore' });
|
|
138
|
-
|
|
139
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
140
|
-
|
|
141
|
-
console.log('\nStep 2: Testing Native CDP...');
|
|
142
|
-
const nativeResult = await testExposeFunctionNewTab(9230, 'Native CDP');
|
|
143
|
-
|
|
144
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
145
|
-
|
|
146
|
-
console.log('\nStep 3: Testing CDP Tunnel...');
|
|
147
|
-
const tunnelResult = await testExposeFunctionNewTab(9221, 'CDP Tunnel');
|
|
148
|
-
|
|
149
|
-
try { process.kill(-chromiumProcess.pid); } catch (e) {}
|
|
150
|
-
|
|
151
|
-
console.log('\n' + '='.repeat(60));
|
|
152
|
-
console.log(`Native CDP: ${nativeResult ? '✓ PASS' : '✗ FAIL'}`);
|
|
153
|
-
console.log(`CDP Tunnel: ${tunnelResult ? '✓ PASS' : '✗ FAIL'}`);
|
|
154
|
-
|
|
155
|
-
if (nativeResult && tunnelResult) {
|
|
156
|
-
console.log('\n✓ Both work identically!');
|
|
157
|
-
} else if (!nativeResult && tunnelResult) {
|
|
158
|
-
console.log('\n✓ CDP Tunnel works! Native CDP has limitations.');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
process.exit(0);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
main();
|