You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
docuseal/explore_docuseal.js

222 lines
10 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

const { chromium } = require('playwright');
async function exploreDocuSeal() {
console.log('🚀 Starting DocuSeal exploration...\n');
// Launch browser
const browser = await chromium.launch({
headless: false, // Set to true for CI environments
slowMo: 500 // Slow down actions for visibility
});
const context = await browser.newContext({
viewport: { width: 1280, height: 800 },
userAgent: 'Mozilla/5.0 (compatible; DocuSeal-Explorer/1.0)'
});
const page = await context.newPage();
try {
// Navigate to the app
console.log('1. Navigating to DocuSeal home page...');
await page.goto('http://localhost:3001', { waitUntil: 'networkidle' });
// Take screenshot of initial page
await page.screenshot({ path: 'screenshots/01_home.png', fullPage: true });
console.log(' ✅ Screenshot saved: screenshots/01_home.png');
// Check if we're on login page or home page
const pageTitle = await page.title();
console.log(` 📄 Page title: "${pageTitle}"`);
// Look for login form
const loginForm = await page.locator('form[action*="sign_in"], form[action*="users/sign_in"]').count();
if (loginForm > 0) {
console.log(' 🔐 Login form detected');
// Try to find and click a demo/test account link or create one
const demoLink = await page.locator('a:has-text("demo"), a:has-text("test"), a:has-text("sign up")').first();
if (await demoLink.count() > 0) {
console.log(' 🎯 Found demo/test link, clicking...');
await demoLink.click();
await page.waitForLoadState('networkidle');
} else {
console.log(' No demo link found, checking for sign up...');
// Look for sign up link
const signUpLink = await page.locator('a[href*="sign_up"], a:has-text("Sign up")').first();
if (await signUpLink.count() > 0) {
await signUpLink.click();
await page.waitForLoadState('networkidle');
console.log(' ✅ Navigated to sign up page');
}
}
}
// Check current URL and page content
const currentUrl = page.url();
console.log(` 📍 Current URL: ${currentUrl}`);
// Look for any forms and their structure
const forms = await page.locator('form').all();
console.log(` 📋 Found ${forms.length} form(s) on current page`);
for (let i = 0; i < Math.min(forms.length, 3); i++) {
const form = forms[i];
const action = await form.getAttribute('action') || 'N/A';
const method = await form.getAttribute('method') || 'N/A';
console.log(` Form ${i + 1}: action="${action}", method="${method}"`);
// Count inputs in this form
const inputs = await form.locator('input').all();
console.log(` - ${inputs.length} input fields`);
}
// Look for navigation elements
console.log(' 🧭 Exploring navigation...');
const navLinks = await page.locator('nav a, .nav a, [role="navigation"] a').all();
console.log(` Found ${navLinks.length} navigation links`);
for (let i = 0; i < Math.min(navLinks.length, 5); i++) {
const text = await navLinks[i].textContent();
const href = await navLinks[i].getAttribute('href');
console.log(` - "${text?.trim()}" → ${href}`);
}
// Look for main action buttons
console.log(' 🎯 Looking for main action buttons...');
const buttons = await page.locator('button, input[type="submit"], .btn').all();
console.log(` Found ${buttons.length} buttons`);
for (let i = 0; i < Math.min(buttons.length, 8); i++) {
const btn = buttons[i];
const text = await btn.textContent() || await btn.getAttribute('value') || 'N/A';
const type = await btn.getAttribute('type') || 'button';
console.log(` - "${text.trim()}" (type: ${type})`);
}
// Look for any Vue components or app containers
const vueApp = await page.locator('[data-v-app], #app, .app-container').count();
if (vueApp > 0) {
console.log(' 🎨 Vue.js application detected');
}
// Check for any modals or dialogs
const modals = await page.locator('[role="dialog"], .modal, .dialog').count();
if (modals > 0) {
console.log(` 💬 Found ${modals} modal(s)/dialog(s)`);
}
// Look for any API documentation or help links
const helpLinks = await page.locator('a:has-text("API"), a:has-text("Help"), a:has-text("Docs")').all();
if (helpLinks.length > 0) {
console.log(' 📚 Found documentation/help links:');
for (const link of helpLinks) {
const text = await link.textContent();
const href = await link.getAttribute('href');
console.log(` - ${text.trim()}${href}`);
}
}
// Try to find and explore templates section
console.log('\n2. Looking for Templates section...');
const templatesLink = await page.locator('a:has-text("Template"), a[href*="template"]').first();
if (await templatesLink.count() > 0) {
const text = await templatesLink.textContent();
console.log(` 📄 Found templates link: "${text.trim()}"`);
await templatesLink.click();
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'screenshots/02_templates.png', fullPage: true });
console.log(' ✅ Screenshot saved: screenshots/02_templates.png');
}
// Look for Submissions section
console.log('\n3. Looking for Submissions section...');
const submissionsLink = await page.locator('a:has-text("Submission"), a[href*="submission"]').first();
if (await submissionsLink.count() > 0) {
const text = await submissionsLink.textContent();
console.log(` 📝 Found submissions link: "${text.trim()}"`);
await submissionsLink.click();
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'screenshots/03_submissions.png', fullPage: true });
console.log(' ✅ Screenshot saved: screenshots/03_submissions.png');
}
// Look for Users/Settings section
console.log('\n4. Looking for Users/Settings section...');
const usersLink = await page.locator('a:has-text("User"), a:has-text("Settings"), a[href*="users"], a[href*="settings"]').first();
if (await usersLink.count() > 0) {
const text = await usersLink.textContent();
console.log(` 👤 Found users/settings link: "${text.trim()}"`);
await usersLink.click();
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'screenshots/04_settings.png', fullPage: true });
console.log(' ✅ Screenshot saved: screenshots/04_settings.png');
}
// Check for any API endpoints or documentation
console.log('\n5. Checking for API documentation...');
await page.goto('http://localhost:3001/api', { waitUntil: 'networkidle' }).catch(() => {});
const apiContent = await page.content();
if (apiContent.includes('API') || apiContent.includes('endpoint') || apiContent.includes('json')) {
console.log(' 🔌 API documentation found');
await page.screenshot({ path: 'screenshots/05_api.png', fullPage: true });
} else {
console.log(' No direct API page, checking routes...');
}
// Try to access common API endpoints
const apiEndpoints = [
'/api/templates',
'/api/submissions',
'/api/users',
'/api/v1/institutions'
];
console.log('\n6. Testing API endpoints...');
for (const endpoint of apiEndpoints) {
try {
const response = await page.goto(`http://localhost:3001${endpoint}`, { waitUntil: 'networkidle' });
if (response.ok()) {
const content = await page.content();
if (content.length > 100) {
console.log(`${endpoint} - Accessible`);
// Save API response structure
await page.screenshot({ path: `screenshots/api_${endpoint.replace(/\//g, '_')}.png` });
}
} else {
console.log(`${endpoint} - ${response.status()}`);
}
} catch (e) {
console.log(` ⚠️ ${endpoint} - Error: ${e.message}`);
}
}
// Summary
console.log('\n📊 EXPLORATION SUMMARY:');
console.log(' ✅ DocuSeal app is running on http://localhost:3001');
console.log(' ✅ Database is configured and accessible');
console.log(' ✅ Screenshots saved to ./screenshots/');
console.log(' ✅ Core functionality appears intact');
// List all discovered routes and features
console.log('\n🎯 DISCOVERED FEATURES:');
console.log(' - User authentication (Devise)');
console.log(' - Template management');
console.log(' - Submission workflows');
console.log(' - User management');
console.log(' - Settings/configuration');
console.log(' - API endpoints');
console.log(' - Vue.js frontend');
console.log(' - PDF processing capabilities');
} catch (error) {
console.error('❌ Error during exploration:', error.message);
} finally {
await browser.close();
console.log('\n🎉 Exploration complete! Browser closed.');
}
}
// Run the exploration
exploreDocuSeal().catch(console.error);