154 lines
4.7 KiB
JavaScript
154 lines
4.7 KiB
JavaScript
import { startServer, stopServer, getServerUrl } from '../helpers/startServer.js';
|
|
import { startTestSite, stopTestSite, getTestSiteUrl } from '../helpers/testSite.js';
|
|
import { createClient } from '../helpers/client.js';
|
|
|
|
describe('Tab Recycling', () => {
|
|
let serverUrl;
|
|
let testSiteUrl;
|
|
|
|
beforeAll(async () => {
|
|
await startServer(0, { MAX_TABS_PER_SESSION: '5', MAX_TABS_GLOBAL: '50' });
|
|
serverUrl = getServerUrl();
|
|
await startTestSite();
|
|
testSiteUrl = getTestSiteUrl();
|
|
}, 120000);
|
|
|
|
afterAll(async () => {
|
|
await stopTestSite();
|
|
await stopServer();
|
|
}, 30000);
|
|
|
|
test('POST /tabs recycles oldest tab when per-session limit reached', async () => {
|
|
const client = createClient(serverUrl);
|
|
try {
|
|
const tabs = [];
|
|
// Fill up to the limit (5)
|
|
for (let i = 0; i < 5; i++) {
|
|
const result = await client.createTab(`${testSiteUrl}/pageA`);
|
|
tabs.push(result.tabId);
|
|
}
|
|
|
|
// 6th tab should succeed via recycling
|
|
const result = await client.createTab(`${testSiteUrl}/pageB`);
|
|
expect(result.tabId).toBeDefined();
|
|
expect(result.url).toContain('/pageB');
|
|
|
|
// The oldest tab (tabs[0]) should be gone
|
|
try {
|
|
await client.getSnapshot(tabs[0]);
|
|
fail('Oldest tab should have been recycled');
|
|
} catch (err) {
|
|
expect(err.status).toBe(410);
|
|
}
|
|
|
|
// The new tab should work
|
|
const snap = await client.getSnapshot(result.tabId);
|
|
expect(snap.url).toContain('/pageB');
|
|
} finally {
|
|
await client.cleanup();
|
|
}
|
|
}, 120000);
|
|
|
|
test('can browse many sites sequentially beyond the tab limit', async () => {
|
|
const client = createClient(serverUrl);
|
|
try {
|
|
// Simulate a cron job visiting 12 different URLs (limit is 5)
|
|
const urls = [];
|
|
for (let i = 0; i < 12; i++) {
|
|
urls.push(`${testSiteUrl}/page${i}`);
|
|
}
|
|
|
|
const tabs = [];
|
|
for (const url of urls) {
|
|
const result = await client.createTab(url);
|
|
expect(result.tabId).toBeDefined();
|
|
tabs.push(result.tabId);
|
|
}
|
|
|
|
// The last tab should be functional
|
|
const lastTab = tabs[tabs.length - 1];
|
|
const snap = await client.getSnapshot(lastTab);
|
|
expect(snap.url).toContain('/page11');
|
|
} finally {
|
|
await client.cleanup();
|
|
}
|
|
}, 120000);
|
|
|
|
test('recycled tabs are the least-used ones', async () => {
|
|
const client = createClient(serverUrl);
|
|
try {
|
|
const tabs = [];
|
|
for (let i = 0; i < 5; i++) {
|
|
const result = await client.createTab(`${testSiteUrl}/pageA`);
|
|
tabs.push(result.tabId);
|
|
}
|
|
|
|
// Interact with tabs[1] through tabs[4] to increase their toolCalls
|
|
for (let i = 1; i < 5; i++) {
|
|
await client.getSnapshot(tabs[i]);
|
|
}
|
|
|
|
// Create a 6th tab -- should recycle tabs[0] (fewest toolCalls)
|
|
const result = await client.createTab(`${testSiteUrl}/pageB`);
|
|
expect(result.tabId).toBeDefined();
|
|
|
|
// tabs[0] should be recycled (least used)
|
|
try {
|
|
await client.getSnapshot(tabs[0]);
|
|
fail('Least-used tab should have been recycled');
|
|
} catch (err) {
|
|
expect(err.status).toBe(410);
|
|
}
|
|
|
|
// tabs[1] should still exist (it had more toolCalls)
|
|
const snap = await client.getSnapshot(tabs[1]);
|
|
expect(snap).toBeDefined();
|
|
} finally {
|
|
await client.cleanup();
|
|
}
|
|
}, 120000);
|
|
|
|
test('navigate returns 404 for unknown tab (no auto-create)', async () => {
|
|
const client = createClient(serverUrl);
|
|
try {
|
|
const tabs = [];
|
|
for (let i = 0; i < 5; i++) {
|
|
const result = await client.createTab(`${testSiteUrl}/pageA`);
|
|
tabs.push(result.tabId);
|
|
}
|
|
|
|
// Navigate with a non-existent tabId -- should return stale-tab error
|
|
const fakeTabId = 'nonexistent-tab-id';
|
|
try {
|
|
await client.navigate(fakeTabId, `${testSiteUrl}/pageC`);
|
|
fail('Should have thrown 404');
|
|
} catch (err) {
|
|
expect(err.status).toBe(404);
|
|
}
|
|
} finally {
|
|
await client.cleanup();
|
|
}
|
|
}, 120000);
|
|
|
|
test('different users can each use their full per-session limit', async () => {
|
|
const client1 = createClient(serverUrl);
|
|
const client2 = createClient(serverUrl);
|
|
try {
|
|
// User 1 fills their session
|
|
for (let i = 0; i < 5; i++) {
|
|
const result = await client1.createTab(`${testSiteUrl}/pageA`);
|
|
expect(result.tabId).toBeDefined();
|
|
}
|
|
|
|
// User 2 should also be able to create tabs (global limit is 50)
|
|
for (let i = 0; i < 5; i++) {
|
|
const result = await client2.createTab(`${testSiteUrl}/pageB`);
|
|
expect(result.tabId).toBeDefined();
|
|
}
|
|
} finally {
|
|
await client1.cleanup();
|
|
await client2.cleanup();
|
|
}
|
|
}, 120000);
|
|
});
|