Skip to content

Commit b85d33b

Browse files
committed
refactor(session): consolidate Session and SessionInfo types in SessionTracker
1 parent aff744f commit b85d33b

File tree

8 files changed

+281
-261
lines changed

8 files changed

+281
-261
lines changed

packages/agent/src/tools/session/SessionTracker.ts

Lines changed: 170 additions & 162 deletions
Large diffs are not rendered by default.

packages/agent/src/tools/session/lib/browser-manager.test.ts

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,33 @@ describe('SessionTracker', () => {
1919

2020
describe('createSession', () => {
2121
it('should create a new browser session', async () => {
22-
const session = await browserTracker.createSession();
23-
expect(session.id).toBeDefined();
24-
expect(session.browser).toBeDefined();
25-
expect(session.page).toBeDefined();
22+
const sessionId = await browserTracker.createSession();
23+
expect(sessionId).toBeDefined();
24+
25+
const sessionInfo = browserTracker.getSessionById(sessionId);
26+
expect(sessionInfo).toBeDefined();
27+
expect(sessionInfo?.page).toBeDefined();
2628
});
2729

2830
it('should create a headless session when specified', async () => {
29-
const session = await browserTracker.createSession({ headless: true });
30-
expect(session.id).toBeDefined();
31+
const sessionId = await browserTracker.createSession({ headless: true });
32+
expect(sessionId).toBeDefined();
33+
34+
const sessionInfo = browserTracker.getSessionById(sessionId);
35+
expect(sessionInfo).toBeDefined();
3136
});
3237

3338
it('should apply custom timeout when specified', async () => {
3439
const customTimeout = 500;
35-
const session = await browserTracker.createSession({
40+
const sessionId = await browserTracker.createSession({
3641
defaultTimeout: customTimeout,
3742
});
43+
44+
const page = browserTracker.getSessionPage(sessionId);
45+
3846
// Verify timeout by attempting to wait for a non-existent element
3947
try {
40-
await session.page.waitForSelector('#nonexistent', {
48+
await page.waitForSelector('#nonexistent', {
4149
timeout: customTimeout - 100,
4250
});
4351
} catch (error: any) {
@@ -49,12 +57,12 @@ describe('SessionTracker', () => {
4957

5058
describe('closeSession', () => {
5159
it('should close an existing session', async () => {
52-
const session = await browserTracker.createSession();
53-
await browserTracker.closeSession(session.id);
60+
const sessionId = await browserTracker.createSession();
61+
await browserTracker.closeSession(sessionId);
5462

55-
expect(() => {
56-
browserTracker.getSession(session.id);
57-
}).toThrow(BrowserError);
63+
const sessionInfo = browserTracker.getSessionById(sessionId);
64+
expect(sessionInfo?.status).toBe(SessionStatus.COMPLETED);
65+
expect(sessionInfo?.page).toBeUndefined();
5866
});
5967

6068
it('should throw error when closing non-existent session', async () => {
@@ -64,16 +72,16 @@ describe('SessionTracker', () => {
6472
});
6573
});
6674

67-
describe('getSession', () => {
68-
it('should return existing session', async () => {
69-
const session = await browserTracker.createSession();
70-
const retrieved = browserTracker.getSession(session.id);
71-
expect(retrieved.id).toBe(session.id);
75+
describe('getSessionPage', () => {
76+
it('should return page for existing session', async () => {
77+
const sessionId = await browserTracker.createSession();
78+
const page = browserTracker.getSessionPage(sessionId);
79+
expect(page).toBeDefined();
7280
});
7381

7482
it('should throw error for non-existent session', () => {
7583
expect(() => {
76-
browserTracker.getSession('invalid-id');
84+
browserTracker.getSessionPage('invalid-id');
7785
}).toThrow(
7886
new BrowserError('Session not found', BrowserErrorCode.SESSION_ERROR),
7987
);

packages/agent/src/tools/session/lib/element-state.test.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,21 @@ import {
1111
import { MockLogger } from '../../../utils/mockLogger.js';
1212
import { SessionTracker } from '../SessionTracker.js';
1313

14-
import { Session } from './types.js';
14+
import type { Page } from '@playwright/test';
1515

1616
// Set global timeout for all tests in this file
1717
vi.setConfig({ testTimeout: 15000 });
1818

1919
describe('Element State Tests', () => {
2020
let browserManager: SessionTracker;
21-
let session: Session;
21+
let sessionId: string;
22+
let page: Page;
2223
const baseUrl = 'https://the-internet.herokuapp.com';
2324

2425
beforeAll(async () => {
2526
browserManager = new SessionTracker('test-agent', new MockLogger());
26-
session = await browserManager.createSession({ headless: true });
27+
sessionId = await browserManager.createSession({ headless: true });
28+
page = browserManager.getSessionPage(sessionId);
2729
});
2830

2931
afterAll(async () => {
@@ -32,11 +34,11 @@ describe('Element State Tests', () => {
3234

3335
describe('Checkbox Tests', () => {
3436
beforeEach(async () => {
35-
await session.page.goto(`${baseUrl}/checkboxes`);
37+
await page.goto(`${baseUrl}/checkboxes`);
3638
});
3739

3840
it('should verify initial checkbox states', async () => {
39-
const checkboxes = await session.page.$$('input[type="checkbox"]');
41+
const checkboxes = await page.$$('input[type="checkbox"]');
4042
expect(checkboxes).toHaveLength(2);
4143

4244
const initialStates: boolean[] = [];
@@ -52,7 +54,7 @@ describe('Element State Tests', () => {
5254
});
5355

5456
it('should toggle checkbox states', async () => {
55-
const checkboxes = await session.page.$$('input[type="checkbox"]');
57+
const checkboxes = await page.$$('input[type="checkbox"]');
5658
if (!checkboxes[0] || !checkboxes[1])
5759
throw new Error('Checkboxes not found');
5860

@@ -72,13 +74,13 @@ describe('Element State Tests', () => {
7274
});
7375

7476
it('should maintain checkbox states after page refresh', async () => {
75-
const checkboxes = await session.page.$$('input[type="checkbox"]');
77+
const checkboxes = await page.$$('input[type="checkbox"]');
7678
if (!checkboxes[0]) throw new Error('First checkbox not found');
7779
await checkboxes[0].click(); // Toggle first checkbox
7880

79-
await session.page.reload();
81+
await page.reload();
8082

81-
const newCheckboxes = await session.page.$$('input[type="checkbox"]');
83+
const newCheckboxes = await page.$$('input[type="checkbox"]');
8284
const states: boolean[] = [];
8385
for (const checkbox of newCheckboxes) {
8486
const isChecked = await checkbox.evaluate(
@@ -95,24 +97,24 @@ describe('Element State Tests', () => {
9597

9698
describe('Dynamic Controls Tests', () => {
9799
beforeEach(async () => {
98-
await session.page.goto(`${baseUrl}/dynamic_controls`);
100+
await page.goto(`${baseUrl}/dynamic_controls`);
99101
});
100102

101103
it('should handle enabled/disabled element states', async () => {
102104
// Wait for the input to be present and verify initial disabled state
103-
await session.page.waitForSelector('input[type="text"][disabled]');
105+
await page.waitForSelector('input[type="text"][disabled]');
104106

105107
// Click the enable button
106-
await session.page.click('button:has-text("Enable")');
108+
await page.click('button:has-text("Enable")');
107109

108110
// Wait for the message indicating the input is enabled
109-
await session.page.waitForSelector('#message', {
111+
await page.waitForSelector('#message', {
110112
state: 'visible',
111113
timeout: 5000,
112114
});
113115

114116
// Verify the input is now enabled
115-
const input = await session.page.waitForSelector(
117+
const input = await page.waitForSelector(
116118
'input[type="text"]:not([disabled])',
117119
{
118120
state: 'visible',
@@ -128,4 +130,4 @@ describe('Element State Tests', () => {
128130
expect(isEnabled).toBe(true);
129131
});
130132
});
131-
});
133+
});

packages/agent/src/tools/session/lib/form-interaction.test.ts

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,59 +11,61 @@ import {
1111
import { MockLogger } from '../../../utils/mockLogger.js';
1212
import { SessionTracker } from '../SessionTracker.js';
1313

14-
import { Session } from './types.js';
14+
import type { Page } from '@playwright/test';
1515

1616
// Set global timeout for all tests in this file
1717
vi.setConfig({ testTimeout: 15000 });
1818

1919
describe('Form Interaction Tests', () => {
2020
let browserManager: SessionTracker;
21-
let session: Session;
21+
let sessionId: string;
22+
let page: Page;
2223
const baseUrl = 'https://the-internet.herokuapp.com';
2324

2425
beforeAll(async () => {
2526
browserManager = new SessionTracker('test-agent', new MockLogger());
26-
session = await browserManager.createSession({ headless: true });
27+
sessionId = await browserManager.createSession({ headless: true });
28+
page = browserManager.getSessionPage(sessionId);
2729
});
2830

2931
afterAll(async () => {
3032
await browserManager.closeAllSessions();
3133
});
3234

3335
beforeEach(async () => {
34-
await session.page.goto(`${baseUrl}/login`);
36+
await page.goto(`${baseUrl}/login`);
3537
});
3638

3739
it('should handle login form with invalid credentials', async () => {
38-
await session.page.type('#username', 'invalid_user');
39-
await session.page.type('#password', 'invalid_pass');
40-
await session.page.click('button[type="submit"]');
40+
await page.type('#username', 'invalid_user');
41+
await page.type('#password', 'invalid_pass');
42+
await page.click('button[type="submit"]');
4143

42-
const flashMessage = await session.page.waitForSelector('#flash');
44+
const flashMessage = await page.waitForSelector('#flash');
4345
const messageText = await flashMessage?.evaluate((el) => el.textContent);
4446
expect(messageText).toContain('Your username is invalid!');
4547
});
4648

4749
it('should clear form fields between attempts', async () => {
48-
await session.page.type('#username', 'test_user');
49-
await session.page.type('#password', 'test_pass');
50+
await page.type('#username', 'test_user');
51+
await page.type('#password', 'test_pass');
5052

5153
// Clear fields
52-
await session.page.$eval(
54+
await page.$eval(
5355
'#username',
5456
(el) => ((el as HTMLInputElement).value = ''),
5557
);
56-
await session.page.$eval(
58+
await page.$eval(
5759
'#password',
5860
(el) => ((el as HTMLInputElement).value = ''),
5961
);
6062

6163
// Verify fields are empty
62-
const username = await session.page.$eval(
64+
const username = await page.$eval(
6365
'#username',
6466
(el) => (el as HTMLInputElement).value,
6567
);
66-
const password = await session.page.$eval(
68+
const password = await page.$eval(
6769
'#password',
6870
(el) => (el as HTMLInputElement).value,
6971
);
@@ -73,11 +75,11 @@ describe('Form Interaction Tests', () => {
7375

7476
it('should maintain form state after page refresh', async () => {
7577
const testUsername = 'persistence_test';
76-
await session.page.type('#username', testUsername);
77-
await session.page.reload();
78+
await page.type('#username', testUsername);
79+
await page.reload();
7880

7981
// Form should be cleared after refresh
80-
const username = await session.page.$eval(
82+
const username = await page.$eval(
8183
'#username',
8284
(el) => (el as HTMLInputElement).value,
8385
);
@@ -86,17 +88,17 @@ describe('Form Interaction Tests', () => {
8688

8789
describe('Content Extraction', () => {
8890
it('should extract form labels and placeholders', async () => {
89-
const usernameLabel = await session.page.$eval(
91+
const usernameLabel = await page.$eval(
9092
'label[for="username"]',
9193
(el) => el.textContent,
9294
);
9395
expect(usernameLabel).toBe('Username');
9496

95-
const passwordPlaceholder = await session.page.$eval(
97+
const passwordPlaceholder = await page.$eval(
9698
'#password',
9799
(el) => (el as HTMLInputElement).placeholder,
98100
);
99101
expect(passwordPlaceholder).toBe('');
100102
});
101103
});
102-
});
104+
});

packages/agent/src/tools/session/lib/navigation.test.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,69 @@ import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
33
import { MockLogger } from '../../../utils/mockLogger.js';
44
import { SessionTracker } from '../SessionTracker.js';
55

6-
import { Session } from './types.js';
6+
import type { Page } from '@playwright/test';
77

88
// Set global timeout for all tests in this file
99
vi.setConfig({ testTimeout: 15000 });
1010

1111
describe('Browser Navigation Tests', () => {
1212
let browserManager: SessionTracker;
13-
let session: Session;
13+
let sessionId: string;
14+
let page: Page;
1415
const baseUrl = 'https://the-internet.herokuapp.com';
1516

1617
beforeAll(async () => {
1718
browserManager = new SessionTracker('test-agent', new MockLogger());
18-
session = await browserManager.createSession({ headless: true });
19+
sessionId = await browserManager.createSession({ headless: true });
20+
page = browserManager.getSessionPage(sessionId);
1921
});
2022

2123
afterAll(async () => {
2224
await browserManager.closeAllSessions();
2325
});
2426

2527
it('should navigate to main page and verify content', async () => {
26-
await session.page.goto(baseUrl);
27-
const title = await session.page.title();
28+
await page.goto(baseUrl);
29+
const title = await page.title();
2830
expect(title).toBe('The Internet');
2931

30-
const headerText = await session.page.$eval(
32+
const headerText = await page.$eval(
3133
'h1.heading',
3234
(el) => el.textContent,
3335
);
3436
expect(headerText).toBe('Welcome to the-internet');
3537
});
3638

3739
it('should navigate to login page and verify title', async () => {
38-
await session.page.goto(`${baseUrl}/login`);
39-
const title = await session.page.title();
40+
await page.goto(`${baseUrl}/login`);
41+
const title = await page.title();
4042
expect(title).toBe('The Internet');
4143

42-
const headerText = await session.page.$eval('h2', (el) => el.textContent);
44+
const headerText = await page.$eval('h2', (el) => el.textContent);
4345
expect(headerText).toBe('Login Page');
4446
});
4547

4648
it('should handle 404 pages appropriately', async () => {
47-
await session.page.goto(`${baseUrl}/nonexistent`);
49+
await page.goto(`${baseUrl}/nonexistent`);
4850

4951
// Wait for the page to stabilize
50-
await session.page.waitForLoadState('networkidle');
52+
await page.waitForLoadState('networkidle');
5153

5254
// Check for 404 content instead of title since title may vary
53-
const bodyText = await session.page.$eval('body', (el) => el.textContent);
55+
const bodyText = await page.$eval('body', (el) => el.textContent);
5456
expect(bodyText).toContain('Not Found');
5557
});
5658

5759
it('should handle navigation timeouts', async () => {
5860
await expect(
59-
session.page.goto(`${baseUrl}/slow`, { timeout: 1 }),
61+
page.goto(`${baseUrl}/slow`, { timeout: 1 }),
6062
).rejects.toThrow();
6163
});
6264

6365
it('should wait for network idle', async () => {
64-
await session.page.goto(baseUrl, {
66+
await page.goto(baseUrl, {
6567
waitUntil: 'networkidle',
6668
});
67-
expect(session.page.url()).toBe(`${baseUrl}/`);
69+
expect(page.url()).toBe(`${baseUrl}/`);
6870
});
6971
});

0 commit comments

Comments
 (0)