refactor(browser): make sessionName optional, add selector filter, deduplicate session setup
- sessionName is now optional in open/exec; skips session restore when omitted - add selector param to open: returns outerHTML or textContent of matched element - extract session restore logic into private setupSession() to remove duplication - replace per-exception instanceof checks with single HttpException base class check - embed label into InternalServerErrorException message instead of logging separately - update MCP tool schemas and HTTP DTOs to reflect optional sessionName and new selector - add integration tests: sessionless open/exec, selector, selector+readerMode
This commit is contained in:
+10
-1
@@ -1,6 +1,15 @@
|
||||
const mockElement = {
|
||||
outerHTML: '<div id="mock">mock content</div>',
|
||||
textContent: 'mock content',
|
||||
};
|
||||
|
||||
export class JSDOM {
|
||||
constructor(public html: string, public options?: any) {}
|
||||
get window() {
|
||||
return { document: {} };
|
||||
return {
|
||||
document: {
|
||||
querySelector: (_selector: string) => mockElement,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,13 +45,6 @@ describe('BrowserController', () => {
|
||||
await request(app.getHttpServer()).post('/open').send({}).expect(400);
|
||||
});
|
||||
|
||||
it('returns 400 when sessionName is missing', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/open')
|
||||
.send({ url: 'https://example.com' })
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it('returns 400 when url is missing', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/open')
|
||||
@@ -65,6 +58,34 @@ describe('BrowserController', () => {
|
||||
.send({ sessionName: 'no-such-session', url: 'https://example.com' })
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('succeeds without a session (sessionless open)', async () => {
|
||||
const res = await request(app.getHttpServer())
|
||||
.post('/open')
|
||||
.send({ url: 'https://example.com' })
|
||||
.expect(201);
|
||||
expect(res.body).toMatchObject({
|
||||
url: expect.any(String),
|
||||
title: expect.any(String),
|
||||
content: expect.any(String),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns only selector content when selector is provided', async () => {
|
||||
const res = await request(app.getHttpServer())
|
||||
.post('/open')
|
||||
.send({ url: 'https://example.com', selector: '#mock' })
|
||||
.expect(201);
|
||||
expect(res.body.content).toBe('<div id="mock">mock content</div>');
|
||||
});
|
||||
|
||||
it('returns selector text content in reader mode', async () => {
|
||||
const res = await request(app.getHttpServer())
|
||||
.post('/open')
|
||||
.send({ url: 'https://example.com', selector: '#mock', readerMode: true })
|
||||
.expect(201);
|
||||
expect(res.body.content).toBe('mock content');
|
||||
});
|
||||
});
|
||||
|
||||
// ── POST /exec ─────────────────────────────────────────────────────────────
|
||||
@@ -94,5 +115,13 @@ describe('BrowserController', () => {
|
||||
.send({ sessionName: 'no-such-session', code: 'return 1;' })
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('succeeds without a session (sessionless exec)', async () => {
|
||||
const res = await request(app.getHttpServer())
|
||||
.post('/exec')
|
||||
.send({ code: 'return 42;' })
|
||||
.expect(201);
|
||||
expect(res.body).toEqual({ result: 42 });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user