let currentSessionId = null;
let isRecording = false;
let recordedActions = [];
async function initBrowser() {
try {
const resp = await fetch('/api/browser/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ headless: false })
});
const data = await resp.json();
currentSessionId = data.id;
document.getElementById('browserCanvas').innerHTML = `
Browser session ${currentSessionId.substring(0,8)} active.
`;
} catch(e) {
alert("Failed to initialize browser");
}
}
async function executeAction(actionType, payload) {
if (!currentSessionId) return;
try {
await fetch(`/api/browser/session/${currentSessionId}/execute`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action_type: actionType, payload })
});
updateTimeline();
captureScreenshot();
} catch(e) {
console.error(e);
}
}
async function toggleRecording() {
if (!currentSessionId) {
alert("Please initialize browser first");
return;
}
const btn = document.getElementById('recordBtn');
if (isRecording) {
// Stop recording
try {
await fetch(`/api/browser/session/${currentSessionId}/record/stop`, { method: 'POST' });
isRecording = false;
btn.textContent = '⏺ Record';
btn.classList.remove('recording-active');
} catch(e) {
console.error(e);
}
} else {
// Start recording
try {
await fetch(`/api/browser/session/${currentSessionId}/record/start`, { method: 'POST' });
isRecording = true;
btn.textContent = '⏹ Stop Recording';
btn.classList.add('recording-active');
} catch(e) {
console.error(e);
}
}
}
async function browserNavigate(url) {
if (!url) return;
if (isRecording) {
recordedActions.push({
type: 'navigate',
value: url,
timestamp: Date.now()
});
}
await executeAction('navigate', { url });
}
async function browserClick(selector) {
if (isRecording) {
recordedActions.push({
type: 'click',
selector: selector,
timestamp: Date.now()
});
}
await executeAction('click', { selector });
}
async function captureScreenshot() {
if (!currentSessionId) return;
try {
await fetch(`/api/browser/session/${currentSessionId}/screenshot`);
// We'd render this to the gallery
const gallery = document.getElementById('browserGallery');
if (gallery) {
gallery.innerHTML = 'Capture
' + gallery.innerHTML;
}
} catch(e) {}
}
async function exportTest() {
if (!currentSessionId) {
alert("No active session");
return;
}
try {
const resp = await fetch(`/api/browser/session/${currentSessionId}/record/export`);
const data = await resp.json();
// Download test file
const blob = new Blob([data.script], { type: 'text/javascript' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = `test-${Date.now()}.spec.js`;
a.click();
} catch(e) {
alert("Export failed");
}
}
function updateTimeline() {
const timeline = document.getElementById('browserTimeline');
if (!timeline) return;
if (recordedActions.length === 0) {
timeline.innerHTML = 'No actions recorded
';
return;
}
timeline.innerHTML = recordedActions.map(action => `
[${action.type}]
${action.selector || action.value || ''}
`).join('');
}