browser.tsโข3.37 kB
import puppeteer, { Browser, Page } from 'puppeteer';
import path from 'path';
import fs from 'fs';
class BrowserManager {
private browser: Browser | null = null;
private page: Page | null = null;
private consoleLogs: string[] = [];
async init() {
if (!this.browser) {
this.browser = await puppeteer.launch({
headless: false, // Visible for demo purposes
defaultViewport: { width: 1280, height: 720 },
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const pages = await this.browser.pages();
this.page = pages[0];
// Setup console log capturing
this.page.on('console', msg => {
const type = msg.type().toUpperCase();
const text = msg.text();
this.consoleLogs.push(`[${type}] ${text}`);
});
}
return this.page!;
}
async navigate(url: string) {
const page = await this.init();
this.consoleLogs = []; // Clear logs on new navigation
await page.goto(url, { waitUntil: 'networkidle0' });
return `Navigated to ${url}`;
}
async setViewport(width: number, height: number, isMobile: boolean = false) {
const page = await this.init();
await page.setViewport({ width, height, isMobile });
return `Viewport set to ${width}x${height} (Mobile: ${isMobile})`;
}
async getConsoleLogs() {
return this.consoleLogs.length > 0
? this.consoleLogs.join('\n')
: 'No console logs captured.';
}
async click(selector: string) {
const page = await this.init();
try {
await page.waitForSelector(selector, { timeout: 5000 });
await page.click(selector);
return `Clicked element: ${selector}`;
} catch (e: any) {
throw new Error(`Failed to click ${selector}: ${e.message}`);
}
}
async type(selector: string, text: string) {
const page = await this.init();
try {
await page.waitForSelector(selector, { timeout: 5000 });
await page.type(selector, text);
return `Typed "${text}" into ${selector}`;
} catch (e: any) {
throw new Error(`Failed to type into ${selector}: ${e.message}`);
}
}
async getText(selector: string) {
const page = await this.init();
try {
await page.waitForSelector(selector, { timeout: 5000 });
const text = await page.$eval(selector, el => el.textContent);
return text?.trim() || '';
} catch (e: any) {
throw new Error(`Failed to get text from ${selector}: ${e.message}`);
}
}
async screenshot(name: string) {
const page = await this.init();
const filename = `${name.replace(/[^a-z0-9]/gi, '_').toLowerCase()}.png`;
const filepath = path.resolve(process.cwd(), filename);
await page.screenshot({ path: filepath });
return `Screenshot saved to ${filepath}`;
}
async close() {
if (this.browser) {
await this.browser.close();
this.browser = null;
this.page = null;
this.consoleLogs = [];
}
}
}
export const browserManager = new BrowserManager();