-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathformAutomationService.js
More file actions
134 lines (114 loc) · 4.3 KB
/
Copy pathformAutomationService.js
File metadata and controls
134 lines (114 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import puppeteer from 'puppeteer';
import fs from 'fs';
import path from 'path';
export class FormAutomationService {
constructor() {
this.browser = null;
this.page = null;
}
async init() {
if (!this.browser) {
// 'new' headless mode es más estable para pintar screenshots
this.browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox'] });
this.page = await this.browser.newPage();
await this.page.setViewport({ width: 1280, height: 800 });
}
}
async fillAndSubmitForm(data) {
try {
await this.init();
await this.page.goto('https://formsmarts.com/form/yx?mode=h5embed&lay=1', { waitUntil: 'networkidle2' });
// --- Llenado ---
const type = async (sel, val) => {
await this.page.waitForSelector(sel);
await this.page.type(sel, val);
};
await type('input[placeholder="Your first name"]', data.firstName);
await type('input[placeholder="Your last name"]', data.lastName);
await type('input[placeholder="Your email address"]', data.email);
await type('textarea[placeholder="Your comment"]', data.inquiry);
if (data.subject) await this.page.select('select', data.subject);
// --- PASO 1: Primer Envío ---
console.log('1. Click inicial...');
await this.clickSubmit();
await this.takeScreenshot('1_intermediate_page');
// --- PASO 2: Confirmación ---
console.log('2. Click de confirmación...');
await this.delay(1000); ///html/body/div[1]/div/form[2]/input[2]
await this.page.waitForSelector('xpath=/html/body/div[1]/div/form[2]/input[2]', { visible: true });
this.page.click('xpath=/html/body/div[1]/div/form[2]/input[2]');
//await this.clickSubmit();
// Espera vital para que cargue el iframe final antes de la foto/extracción
await this.delay(2000);
const intermediateScreenshot = await this.captureScreenshot();
// --- PASO 3: Extracción ---
const refNumber = await this.getReferenceNumber();
const finalScreenshot = await this.captureScreenshot();
return {
success: true,
referenceNumber: refNumber,
screenshots: {
intermediate: intermediateScreenshot,
final: finalScreenshot
}
};
} catch (error) {
console.error('Error:', error.message);
const errShot = await this.captureScreenshot();
return { success: false, error: error.message, screenshot: errShot };
} finally {
await this.close();
}
}
async clickSubmit() {
// Esperamos selectores y navegación simultáneamente
const submitBtn = 'input[type="submit"]';
await this.page.waitForSelector(submitBtn, { visible: true });
await Promise.all([
this.page.waitForNavigation({ waitUntil: 'networkidle2' }),
this.page.click(submitBtn)
]);
}
async getReferenceNumber() {
try {
await this.page.waitForSelector('#refnum', { timeout: 5000 });
const refText = await this.page.$eval('#refnum', el => el.innerText);
return refText.trim();
} catch (e) {
// Fallback si falla el iframe
const bodyText = await this.page.$eval('body', el => el.innerText);
const match = bodyText.match(/(?:Ref|ID|#)[:\s]+([A-Z0-9-]+)/i);
return match ? match[1] : `UNK-${Date.now()}`;
}
}
// Utilidad simple para pausas
delay(time) {
return new Promise(function(resolve) {
setTimeout(resolve, time)
});
}
async takeScreenshot(name) {
const dir = path.join(process.cwd(), 'screenshots');
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
const safeName = name.replace(/[^a-z0-9_-]/gi, '_');
const fileName = `${safeName}_${Date.now()}.png`;
const filePath = path.join(dir, fileName);
await this.page.screenshot({ path: filePath, fullPage: true });
return fileName; // Devolver solo el nombre del archivo, no la ruta completa
}
async captureScreenshot() {
// Captura la screenshot y la devuelve como base64
const screenshot = await this.page.screenshot({
encoding: 'base64',
fullPage: true
});
return `data:image/png;base64,${screenshot}`;
}
async close() {
if (this.browser) {
await this.browser.close();
this.browser = null;
}
}
}
export default new FormAutomationService();