@askjo/camoufox-browser 1.0.2 → 1.0.3
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/package.json +37 -1
- package/.env.bak +0 -4
- package/.github/workflows/deploy.yml +0 -21
- package/AGENTS.md +0 -153
- package/experimental/chromium/Dockerfile +0 -35
- package/experimental/chromium/README.md +0 -47
- package/experimental/chromium/run.sh +0 -24
- package/experimental/chromium/server.js +0 -812
- package/fly.toml +0 -29
- package/jest.config.js +0 -41
- package/tests/e2e/concurrency.test.js +0 -103
- package/tests/e2e/formSubmission.test.js +0 -129
- package/tests/e2e/macroNavigation.test.js +0 -92
- package/tests/e2e/navigation.test.js +0 -128
- package/tests/e2e/scroll.test.js +0 -81
- package/tests/e2e/snapshotLinks.test.js +0 -141
- package/tests/e2e/tabLifecycle.test.js +0 -149
- package/tests/e2e/typingEnter.test.js +0 -147
- package/tests/helpers/client.js +0 -222
- package/tests/helpers/startJoBrowser.js +0 -95
- package/tests/helpers/testSite.js +0 -238
- package/tests/live/googleSearch.test.js +0 -93
- package/tests/live/macroExpansion.test.js +0 -132
- package/tests/unit/macros.test.js +0 -123
package/fly.toml
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
app = "jo-camoufox-browser"
|
|
2
|
-
primary_region = "sjc"
|
|
3
|
-
|
|
4
|
-
[build]
|
|
5
|
-
dockerfile = "Dockerfile.camoufox"
|
|
6
|
-
|
|
7
|
-
# Internal-only service (Fly private network)
|
|
8
|
-
[[services]]
|
|
9
|
-
internal_port = 3000
|
|
10
|
-
protocol = "tcp"
|
|
11
|
-
auto_stop_machines = false
|
|
12
|
-
auto_start_machines = true
|
|
13
|
-
min_machines_running = 1
|
|
14
|
-
|
|
15
|
-
[[services.ports]]
|
|
16
|
-
port = 3000
|
|
17
|
-
|
|
18
|
-
[[services.http_checks]]
|
|
19
|
-
interval = 30000
|
|
20
|
-
timeout = 5000
|
|
21
|
-
path = "/health"
|
|
22
|
-
|
|
23
|
-
[[vm]]
|
|
24
|
-
memory = "4gb"
|
|
25
|
-
cpu_kind = "shared"
|
|
26
|
-
cpus = 2
|
|
27
|
-
|
|
28
|
-
[env]
|
|
29
|
-
NODE_ENV = "production"
|
package/jest.config.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
testEnvironment: 'node',
|
|
3
|
-
testTimeout: 60000, // 60 seconds per test
|
|
4
|
-
|
|
5
|
-
// Run tests sequentially to avoid resource conflicts
|
|
6
|
-
maxWorkers: 1,
|
|
7
|
-
|
|
8
|
-
// Test file patterns
|
|
9
|
-
testMatch: [
|
|
10
|
-
'**/tests/**/*.test.js'
|
|
11
|
-
],
|
|
12
|
-
|
|
13
|
-
// Ignore patterns
|
|
14
|
-
testPathIgnorePatterns: [
|
|
15
|
-
'/node_modules/'
|
|
16
|
-
],
|
|
17
|
-
|
|
18
|
-
// Setup and teardown
|
|
19
|
-
globalSetup: undefined,
|
|
20
|
-
globalTeardown: undefined,
|
|
21
|
-
|
|
22
|
-
// Verbose output
|
|
23
|
-
verbose: true,
|
|
24
|
-
|
|
25
|
-
// Fail fast on first error (useful for CI)
|
|
26
|
-
bail: process.env.CI ? 1 : 0,
|
|
27
|
-
|
|
28
|
-
// Coverage settings (optional)
|
|
29
|
-
collectCoverage: false,
|
|
30
|
-
coverageDirectory: 'coverage',
|
|
31
|
-
coveragePathIgnorePatterns: [
|
|
32
|
-
'/node_modules/',
|
|
33
|
-
'/tests/'
|
|
34
|
-
],
|
|
35
|
-
|
|
36
|
-
// Reporter settings
|
|
37
|
-
reporters: [
|
|
38
|
-
'default',
|
|
39
|
-
...(process.env.CI ? [['jest-junit', { outputDirectory: 'test-results' }]] : [])
|
|
40
|
-
]
|
|
41
|
-
};
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
const { startJoBrowser, stopJoBrowser, getServerUrl } = require('../helpers/startJoBrowser');
|
|
2
|
-
const { startTestSite, stopTestSite, getTestSiteUrl } = require('../helpers/testSite');
|
|
3
|
-
const { createClient } = require('../helpers/client');
|
|
4
|
-
|
|
5
|
-
describe('Concurrency', () => {
|
|
6
|
-
let serverUrl;
|
|
7
|
-
let testSiteUrl;
|
|
8
|
-
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
const port = await startJoBrowser();
|
|
11
|
-
serverUrl = getServerUrl();
|
|
12
|
-
|
|
13
|
-
const testPort = await startTestSite();
|
|
14
|
-
testSiteUrl = getTestSiteUrl();
|
|
15
|
-
}, 120000);
|
|
16
|
-
|
|
17
|
-
afterAll(async () => {
|
|
18
|
-
await stopTestSite();
|
|
19
|
-
await stopJoBrowser();
|
|
20
|
-
}, 30000);
|
|
21
|
-
|
|
22
|
-
test('concurrent operations on same tab are serialized', async () => {
|
|
23
|
-
const client = createClient(serverUrl);
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
|
|
27
|
-
|
|
28
|
-
// Fire multiple operations concurrently on the same tab
|
|
29
|
-
const operations = [
|
|
30
|
-
client.getSnapshot(tabId),
|
|
31
|
-
client.navigate(tabId, `${testSiteUrl}/pageB`),
|
|
32
|
-
client.getSnapshot(tabId),
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
// All should complete without errors (tab locking serializes them)
|
|
36
|
-
const results = await Promise.all(operations);
|
|
37
|
-
|
|
38
|
-
expect(results.length).toBe(3);
|
|
39
|
-
// Each result should be valid (no crashes)
|
|
40
|
-
results.forEach(r => expect(r).toBeDefined());
|
|
41
|
-
} finally {
|
|
42
|
-
await client.cleanup();
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('parallel operations on different tabs work', async () => {
|
|
47
|
-
const client = createClient(serverUrl);
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
// Create two tabs
|
|
51
|
-
const tab1 = await client.createTab(`${testSiteUrl}/pageA`);
|
|
52
|
-
const tab2 = await client.createTab(`${testSiteUrl}/pageB`);
|
|
53
|
-
|
|
54
|
-
// Run operations on both tabs in parallel
|
|
55
|
-
const [snap1, snap2] = await Promise.all([
|
|
56
|
-
client.getSnapshot(tab1.tabId),
|
|
57
|
-
client.getSnapshot(tab2.tabId),
|
|
58
|
-
]);
|
|
59
|
-
|
|
60
|
-
// Both should return valid snapshots
|
|
61
|
-
expect(snap1.snapshot).toContain('Page A');
|
|
62
|
-
expect(snap2.snapshot).toContain('Page B');
|
|
63
|
-
} finally {
|
|
64
|
-
await client.cleanup();
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test('multiple clients can work independently', async () => {
|
|
69
|
-
const client1 = createClient(serverUrl);
|
|
70
|
-
const client2 = createClient(serverUrl);
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
// Each client creates their own tab
|
|
74
|
-
const [tab1, tab2] = await Promise.all([
|
|
75
|
-
client1.createTab(`${testSiteUrl}/pageA`),
|
|
76
|
-
client2.createTab(`${testSiteUrl}/pageB`),
|
|
77
|
-
]);
|
|
78
|
-
|
|
79
|
-
// Verify they are independent
|
|
80
|
-
expect(tab1.tabId).not.toBe(tab2.tabId);
|
|
81
|
-
expect(client1.userId).not.toBe(client2.userId);
|
|
82
|
-
|
|
83
|
-
// Both can operate independently
|
|
84
|
-
const [snap1, snap2] = await Promise.all([
|
|
85
|
-
client1.getSnapshot(tab1.tabId),
|
|
86
|
-
client2.getSnapshot(tab2.tabId),
|
|
87
|
-
]);
|
|
88
|
-
|
|
89
|
-
expect(snap1.snapshot).toContain('Page A');
|
|
90
|
-
expect(snap2.snapshot).toContain('Page B');
|
|
91
|
-
|
|
92
|
-
// Closing one client's session doesn't affect the other
|
|
93
|
-
await client1.closeSession();
|
|
94
|
-
|
|
95
|
-
// Client 2 still works
|
|
96
|
-
const snap2After = await client2.getSnapshot(tab2.tabId);
|
|
97
|
-
expect(snap2After.snapshot).toContain('Page B');
|
|
98
|
-
} finally {
|
|
99
|
-
await client1.cleanup();
|
|
100
|
-
await client2.cleanup();
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
});
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
const { startJoBrowser, stopJoBrowser, getServerUrl } = require('../helpers/startJoBrowser');
|
|
2
|
-
const { startTestSite, stopTestSite, getTestSiteUrl } = require('../helpers/testSite');
|
|
3
|
-
const { createClient } = require('../helpers/client');
|
|
4
|
-
|
|
5
|
-
describe('Form Submission', () => {
|
|
6
|
-
let serverUrl;
|
|
7
|
-
let testSiteUrl;
|
|
8
|
-
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
const port = await startJoBrowser();
|
|
11
|
-
serverUrl = getServerUrl();
|
|
12
|
-
|
|
13
|
-
const testPort = await startTestSite();
|
|
14
|
-
testSiteUrl = getTestSiteUrl();
|
|
15
|
-
}, 120000);
|
|
16
|
-
|
|
17
|
-
afterAll(async () => {
|
|
18
|
-
await stopTestSite();
|
|
19
|
-
await stopJoBrowser();
|
|
20
|
-
}, 30000);
|
|
21
|
-
|
|
22
|
-
test('fill form fields and submit via button click', async () => {
|
|
23
|
-
const client = createClient(serverUrl);
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/form`);
|
|
27
|
-
|
|
28
|
-
// Fill username
|
|
29
|
-
await client.type(tabId, {
|
|
30
|
-
selector: '#username',
|
|
31
|
-
text: 'testuser'
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// Fill email
|
|
35
|
-
await client.type(tabId, {
|
|
36
|
-
selector: '#email',
|
|
37
|
-
text: 'test@example.com'
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// Click submit button
|
|
41
|
-
await client.click(tabId, {
|
|
42
|
-
selector: '#submitBtn'
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Wait for form submission and navigation
|
|
46
|
-
const snapshot = await client.waitForUrl(tabId, '/submitted');
|
|
47
|
-
|
|
48
|
-
expect(snapshot.url).toContain('/submitted');
|
|
49
|
-
expect(snapshot.snapshot).toContain('Form Submitted Successfully');
|
|
50
|
-
expect(snapshot.snapshot).toContain('Username: testuser');
|
|
51
|
-
expect(snapshot.snapshot).toContain('Email: test@example.com');
|
|
52
|
-
} finally {
|
|
53
|
-
await client.cleanup();
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test('click button on page', async () => {
|
|
58
|
-
const client = createClient(serverUrl);
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/click`);
|
|
62
|
-
|
|
63
|
-
// Initial state
|
|
64
|
-
let snapshot = await client.getSnapshot(tabId);
|
|
65
|
-
expect(snapshot.snapshot).not.toContain('Button was clicked!');
|
|
66
|
-
|
|
67
|
-
// Click the button
|
|
68
|
-
await client.click(tabId, {
|
|
69
|
-
selector: '#clickMe'
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// Verify click effect
|
|
73
|
-
snapshot = await client.waitForSnapshotContains(tabId, 'Button was clicked!');
|
|
74
|
-
expect(snapshot.snapshot).toContain('Button was clicked!');
|
|
75
|
-
} finally {
|
|
76
|
-
await client.cleanup();
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test('click using ref', async () => {
|
|
81
|
-
const client = createClient(serverUrl);
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/click`);
|
|
85
|
-
|
|
86
|
-
// Get snapshot to find button ref
|
|
87
|
-
const snapshot = await client.getSnapshot(tabId);
|
|
88
|
-
|
|
89
|
-
// Find ref for "Click Me" button
|
|
90
|
-
const match = snapshot.snapshot.match(/\[(e\d+)\].*button.*Click Me/i);
|
|
91
|
-
|
|
92
|
-
if (match) {
|
|
93
|
-
const ref = match[1];
|
|
94
|
-
await client.click(tabId, { ref });
|
|
95
|
-
|
|
96
|
-
const updatedSnapshot = await client.waitForSnapshotContains(tabId, 'Button was clicked!');
|
|
97
|
-
expect(updatedSnapshot.snapshot).toContain('Button was clicked!');
|
|
98
|
-
} else {
|
|
99
|
-
// Fallback to selector
|
|
100
|
-
await client.click(tabId, { selector: '#clickMe' });
|
|
101
|
-
const updatedSnapshot = await client.waitForSnapshotContains(tabId, 'Button was clicked!');
|
|
102
|
-
expect(updatedSnapshot.snapshot).toContain('Button was clicked!');
|
|
103
|
-
}
|
|
104
|
-
} finally {
|
|
105
|
-
await client.cleanup();
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test('click link to navigate', async () => {
|
|
110
|
-
const client = createClient(serverUrl);
|
|
111
|
-
|
|
112
|
-
try {
|
|
113
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
|
|
114
|
-
|
|
115
|
-
// Click the link to page B
|
|
116
|
-
await client.click(tabId, {
|
|
117
|
-
selector: 'a[href="/pageB"]'
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
// Wait for navigation
|
|
121
|
-
const snapshot = await client.waitForUrl(tabId, '/pageB');
|
|
122
|
-
|
|
123
|
-
expect(snapshot.url).toContain('/pageB');
|
|
124
|
-
expect(snapshot.snapshot).toContain('Page B');
|
|
125
|
-
} finally {
|
|
126
|
-
await client.cleanup();
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
const { startJoBrowser, stopJoBrowser, getServerUrl } = require('../helpers/startJoBrowser');
|
|
2
|
-
const { startTestSite, stopTestSite, getTestSiteUrl } = require('../helpers/testSite');
|
|
3
|
-
const { createClient } = require('../helpers/client');
|
|
4
|
-
|
|
5
|
-
describe('Macro Navigation', () => {
|
|
6
|
-
let serverUrl;
|
|
7
|
-
let testSiteUrl;
|
|
8
|
-
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
const port = await startJoBrowser();
|
|
11
|
-
serverUrl = getServerUrl();
|
|
12
|
-
|
|
13
|
-
const testPort = await startTestSite();
|
|
14
|
-
testSiteUrl = getTestSiteUrl();
|
|
15
|
-
}, 120000);
|
|
16
|
-
|
|
17
|
-
afterAll(async () => {
|
|
18
|
-
await stopTestSite();
|
|
19
|
-
await stopJoBrowser();
|
|
20
|
-
}, 30000);
|
|
21
|
-
|
|
22
|
-
test('unknown macro returns error when no fallback URL', async () => {
|
|
23
|
-
const client = createClient(serverUrl);
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
const { tabId } = await client.createTab();
|
|
27
|
-
|
|
28
|
-
await expect(client.navigate(tabId, '@nonexistent_macro test query'))
|
|
29
|
-
.rejects.toThrow(/url or macro required/);
|
|
30
|
-
} finally {
|
|
31
|
-
await client.cleanup();
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test('client parses @macro syntax correctly', async () => {
|
|
36
|
-
const client = createClient(serverUrl);
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
const { tabId } = await client.createTab();
|
|
40
|
-
|
|
41
|
-
// Navigate to a real URL first so we have a valid tab
|
|
42
|
-
await client.navigate(tabId, `${testSiteUrl}/pageA`);
|
|
43
|
-
|
|
44
|
-
// Now try an unknown macro - if client parsing works,
|
|
45
|
-
// server will receive {macro: "@unknown", query: "with spaces"}
|
|
46
|
-
// and return "url or macro required" error
|
|
47
|
-
await expect(client.navigate(tabId, '@unknown with spaces'))
|
|
48
|
-
.rejects.toThrow(/url or macro required/);
|
|
49
|
-
} finally {
|
|
50
|
-
await client.cleanup();
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('regular URL still works after macro changes', async () => {
|
|
55
|
-
const client = createClient(serverUrl);
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
const { tabId } = await client.createTab();
|
|
59
|
-
|
|
60
|
-
// Regular URL should still work
|
|
61
|
-
const result = await client.navigate(tabId, `${testSiteUrl}/pageA`);
|
|
62
|
-
|
|
63
|
-
expect(result.ok).toBe(true);
|
|
64
|
-
expect(result.url).toContain('/pageA');
|
|
65
|
-
|
|
66
|
-
const snapshot = await client.getSnapshot(tabId);
|
|
67
|
-
expect(snapshot.snapshot).toContain('Page A');
|
|
68
|
-
} finally {
|
|
69
|
-
await client.cleanup();
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test('navigate API accepts macro and query params directly', async () => {
|
|
74
|
-
const client = createClient(serverUrl);
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
const { tabId } = await client.createTab();
|
|
78
|
-
|
|
79
|
-
// Test the raw API with macro param directly (bypass client parsing)
|
|
80
|
-
// Unknown macro should fail
|
|
81
|
-
await expect(
|
|
82
|
-
client.request('POST', `/tabs/${tabId}/navigate`, {
|
|
83
|
-
userId: client.userId,
|
|
84
|
-
macro: '@fake_macro',
|
|
85
|
-
query: 'test'
|
|
86
|
-
})
|
|
87
|
-
).rejects.toThrow(/url or macro required/);
|
|
88
|
-
} finally {
|
|
89
|
-
await client.cleanup();
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
});
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
const { startJoBrowser, stopJoBrowser, getServerUrl } = require('../helpers/startJoBrowser');
|
|
2
|
-
const { startTestSite, stopTestSite, getTestSiteUrl } = require('../helpers/testSite');
|
|
3
|
-
const { createClient } = require('../helpers/client');
|
|
4
|
-
|
|
5
|
-
describe('Navigation', () => {
|
|
6
|
-
let serverUrl;
|
|
7
|
-
let testSiteUrl;
|
|
8
|
-
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
const port = await startJoBrowser();
|
|
11
|
-
serverUrl = getServerUrl();
|
|
12
|
-
|
|
13
|
-
const testPort = await startTestSite();
|
|
14
|
-
testSiteUrl = getTestSiteUrl();
|
|
15
|
-
}, 120000);
|
|
16
|
-
|
|
17
|
-
afterAll(async () => {
|
|
18
|
-
await stopTestSite();
|
|
19
|
-
await stopJoBrowser();
|
|
20
|
-
}, 30000);
|
|
21
|
-
|
|
22
|
-
test('navigate to URL', async () => {
|
|
23
|
-
const client = createClient(serverUrl);
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
const { tabId } = await client.createTab();
|
|
27
|
-
|
|
28
|
-
const result = await client.navigate(tabId, `${testSiteUrl}/pageA`);
|
|
29
|
-
|
|
30
|
-
expect(result.ok).toBe(true);
|
|
31
|
-
expect(result.url).toContain('/pageA');
|
|
32
|
-
|
|
33
|
-
const snapshot = await client.getSnapshot(tabId);
|
|
34
|
-
expect(snapshot.snapshot).toContain('Welcome to Page A');
|
|
35
|
-
} finally {
|
|
36
|
-
await client.cleanup();
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test('navigate back', async () => {
|
|
41
|
-
const client = createClient(serverUrl);
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
|
|
45
|
-
await client.navigate(tabId, `${testSiteUrl}/pageB`);
|
|
46
|
-
|
|
47
|
-
// Verify we're on page B
|
|
48
|
-
let snapshot = await client.getSnapshot(tabId);
|
|
49
|
-
expect(snapshot.snapshot).toContain('Page B');
|
|
50
|
-
|
|
51
|
-
// Go back
|
|
52
|
-
const result = await client.back(tabId);
|
|
53
|
-
expect(result.ok).toBe(true);
|
|
54
|
-
expect(result.url).toContain('/pageA');
|
|
55
|
-
|
|
56
|
-
snapshot = await client.getSnapshot(tabId);
|
|
57
|
-
expect(snapshot.snapshot).toContain('Page A');
|
|
58
|
-
} finally {
|
|
59
|
-
await client.cleanup();
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test('navigate forward', async () => {
|
|
64
|
-
const client = createClient(serverUrl);
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
|
|
68
|
-
await client.navigate(tabId, `${testSiteUrl}/pageB`);
|
|
69
|
-
await client.back(tabId);
|
|
70
|
-
|
|
71
|
-
// Verify we're back on page A
|
|
72
|
-
let snapshot = await client.getSnapshot(tabId);
|
|
73
|
-
expect(snapshot.snapshot).toContain('Page A');
|
|
74
|
-
|
|
75
|
-
// Go forward
|
|
76
|
-
const result = await client.forward(tabId);
|
|
77
|
-
expect(result.ok).toBe(true);
|
|
78
|
-
expect(result.url).toContain('/pageB');
|
|
79
|
-
|
|
80
|
-
snapshot = await client.getSnapshot(tabId);
|
|
81
|
-
expect(snapshot.snapshot).toContain('Page B');
|
|
82
|
-
} finally {
|
|
83
|
-
await client.cleanup();
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test('refresh page', async () => {
|
|
88
|
-
const client = createClient(serverUrl);
|
|
89
|
-
|
|
90
|
-
try {
|
|
91
|
-
// Use the refresh counter page
|
|
92
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/refresh-test`);
|
|
93
|
-
|
|
94
|
-
let snapshot = await client.getSnapshot(tabId);
|
|
95
|
-
const initialMatch = snapshot.snapshot.match(/Count: (\d+)/);
|
|
96
|
-
const initialCount = initialMatch ? parseInt(initialMatch[1]) : 0;
|
|
97
|
-
|
|
98
|
-
// Refresh the page
|
|
99
|
-
const result = await client.refresh(tabId);
|
|
100
|
-
expect(result.ok).toBe(true);
|
|
101
|
-
|
|
102
|
-
snapshot = await client.getSnapshot(tabId);
|
|
103
|
-
const newMatch = snapshot.snapshot.match(/Count: (\d+)/);
|
|
104
|
-
const newCount = newMatch ? parseInt(newMatch[1]) : 0;
|
|
105
|
-
|
|
106
|
-
// Count should have incremented
|
|
107
|
-
expect(newCount).toBe(initialCount + 1);
|
|
108
|
-
} finally {
|
|
109
|
-
await client.cleanup();
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test('navigation updates visited URLs', async () => {
|
|
114
|
-
const client = createClient(serverUrl);
|
|
115
|
-
|
|
116
|
-
try {
|
|
117
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
|
|
118
|
-
await client.navigate(tabId, `${testSiteUrl}/pageB`);
|
|
119
|
-
|
|
120
|
-
const stats = await client.getStats(tabId);
|
|
121
|
-
|
|
122
|
-
expect(stats.visitedUrls).toContain(`${testSiteUrl}/pageA`);
|
|
123
|
-
expect(stats.visitedUrls).toContain(`${testSiteUrl}/pageB`);
|
|
124
|
-
} finally {
|
|
125
|
-
await client.cleanup();
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
});
|
package/tests/e2e/scroll.test.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
const { startJoBrowser, stopJoBrowser, getServerUrl } = require('../helpers/startJoBrowser');
|
|
2
|
-
const { startTestSite, stopTestSite, getTestSiteUrl } = require('../helpers/testSite');
|
|
3
|
-
const { createClient } = require('../helpers/client');
|
|
4
|
-
|
|
5
|
-
describe('Scroll', () => {
|
|
6
|
-
let serverUrl;
|
|
7
|
-
let testSiteUrl;
|
|
8
|
-
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
const port = await startJoBrowser();
|
|
11
|
-
serverUrl = getServerUrl();
|
|
12
|
-
|
|
13
|
-
const testPort = await startTestSite();
|
|
14
|
-
testSiteUrl = getTestSiteUrl();
|
|
15
|
-
}, 120000);
|
|
16
|
-
|
|
17
|
-
afterAll(async () => {
|
|
18
|
-
await stopTestSite();
|
|
19
|
-
await stopJoBrowser();
|
|
20
|
-
}, 30000);
|
|
21
|
-
|
|
22
|
-
test('scroll down page', async () => {
|
|
23
|
-
const client = createClient(serverUrl);
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/scroll`);
|
|
27
|
-
|
|
28
|
-
// Scroll down
|
|
29
|
-
const result = await client.scroll(tabId, {
|
|
30
|
-
direction: 'down',
|
|
31
|
-
amount: 500
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
expect(result.ok).toBe(true);
|
|
35
|
-
} finally {
|
|
36
|
-
await client.cleanup();
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test('scroll to bottom of page', async () => {
|
|
41
|
-
const client = createClient(serverUrl);
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/scroll`);
|
|
45
|
-
|
|
46
|
-
// Scroll to bottom
|
|
47
|
-
const result = await client.scroll(tabId, {
|
|
48
|
-
direction: 'down',
|
|
49
|
-
amount: 10000 // Large number to reach bottom
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
expect(result.ok).toBe(true);
|
|
53
|
-
|
|
54
|
-
// The snapshot might now include "Bottom of page" text
|
|
55
|
-
// (depending on viewport and scroll behavior)
|
|
56
|
-
} finally {
|
|
57
|
-
await client.cleanup();
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test('scroll up page', async () => {
|
|
62
|
-
const client = createClient(serverUrl);
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
const { tabId } = await client.createTab(`${testSiteUrl}/scroll`);
|
|
66
|
-
|
|
67
|
-
// First scroll down
|
|
68
|
-
await client.scroll(tabId, { direction: 'down', amount: 1000 });
|
|
69
|
-
|
|
70
|
-
// Then scroll up
|
|
71
|
-
const result = await client.scroll(tabId, {
|
|
72
|
-
direction: 'up',
|
|
73
|
-
amount: 500
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
expect(result.ok).toBe(true);
|
|
77
|
-
} finally {
|
|
78
|
-
await client.cleanup();
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|