feat: city autocomplete dropdown, phone country code, checkboxes, EEO selects, location/heard-about answers
This commit is contained in:
@@ -47,9 +47,14 @@ export class FormFiller {
|
|||||||
if (l.includes('city') && !l.includes('remote')) return p.location?.city || null;
|
if (l.includes('city') && !l.includes('remote')) return p.location?.city || null;
|
||||||
if (l.includes('state') && !l.includes('statement')) return p.location?.state || null;
|
if (l.includes('state') && !l.includes('statement')) return p.location?.state || null;
|
||||||
if (l.includes('zip') || l.includes('postal')) return p.location?.zip || null;
|
if (l.includes('zip') || l.includes('postal')) return p.location?.zip || null;
|
||||||
if (l.includes('country')) return p.location?.country || null;
|
if (l.includes('country') && !l.includes('code')) return p.location?.country || null;
|
||||||
|
if (l.includes('country code') || l.includes('phone country')) return 'United States (+1)';
|
||||||
if (l.includes('linkedin')) return p.linkedin_url || null;
|
if (l.includes('linkedin')) return p.linkedin_url || null;
|
||||||
if (l.includes('website') || l.includes('portfolio')) return p.linkedin_url || null;
|
if (l.includes('website') || l.includes('portfolio')) return p.linkedin_url || null;
|
||||||
|
if (l.includes('currently located') || l.includes('current location') || l.includes('where are you')) {
|
||||||
|
return `${p.location?.city || ''}, ${p.location?.state || ''}`.trim().replace(/^,\s*|,\s*$/, '');
|
||||||
|
}
|
||||||
|
if (l.includes('hear about') || l.includes('how did you find') || l.includes('how did you hear')) return 'LinkedIn';
|
||||||
|
|
||||||
// Work auth
|
// Work auth
|
||||||
if (l.includes('sponsor') || l.includes('visa')) return p.work_authorization?.requires_sponsorship ? 'Yes' : 'No';
|
if (l.includes('sponsor') || l.includes('visa')) return p.work_authorization?.requires_sponsorship ? 'Yes' : 'No';
|
||||||
@@ -151,6 +156,14 @@ export class FormFiller {
|
|||||||
const answer = this.answerFor(lbl);
|
const answer = this.answerFor(lbl);
|
||||||
if (answer && answer !== this.profile.cover_letter) {
|
if (answer && answer !== this.profile.cover_letter) {
|
||||||
await inp.fill(String(answer)).catch(() => {});
|
await inp.fill(String(answer)).catch(() => {});
|
||||||
|
// Handle city/location autocomplete dropdowns
|
||||||
|
if (lbl.toLowerCase().includes('city') || lbl.toLowerCase().includes('location') || lbl.toLowerCase().includes('located')) {
|
||||||
|
await page.waitForTimeout(800);
|
||||||
|
const dropdown = await page.$('[role="listbox"], [role="option"], ul[class*="autocomplete"] li').catch(() => null);
|
||||||
|
if (dropdown) {
|
||||||
|
await page.click('[role="option"]:first-child, [role="listbox"] li:first-child').catch(() => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (!answer) {
|
} else if (!answer) {
|
||||||
const required = await inp.getAttribute('required').catch(() => null);
|
const required = await inp.getAttribute('required').catch(() => null);
|
||||||
if (required !== null) unknown.push(lbl);
|
if (required !== null) unknown.push(lbl);
|
||||||
@@ -191,7 +204,6 @@ export class FormFiller {
|
|||||||
for (const sel of await page.$$('select')) {
|
for (const sel of await page.$$('select')) {
|
||||||
if (!await sel.isVisible().catch(() => false)) continue;
|
if (!await sel.isVisible().catch(() => false)) continue;
|
||||||
const lbl = await this.getLabel(sel);
|
const lbl = await this.getLabel(sel);
|
||||||
if (lbl.toLowerCase().includes('country code')) continue;
|
|
||||||
const existing = await sel.inputValue().catch(() => '');
|
const existing = await sel.inputValue().catch(() => '');
|
||||||
if (existing) continue;
|
if (existing) continue;
|
||||||
const answer = this.answerFor(lbl);
|
const answer = this.answerFor(lbl);
|
||||||
@@ -199,9 +211,38 @@ export class FormFiller {
|
|||||||
await sel.selectOption({ label: answer }).catch(async () => {
|
await sel.selectOption({ label: answer }).catch(async () => {
|
||||||
await sel.selectOption({ value: answer }).catch(() => {});
|
await sel.selectOption({ value: answer }).catch(() => {});
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
// EEO/voluntary fields — default to "Prefer not to disclose"
|
||||||
|
const l = lbl.toLowerCase();
|
||||||
|
if (l.includes('race') || l.includes('ethnicity') || l.includes('gender') ||
|
||||||
|
l.includes('veteran') || l.includes('disability') || l.includes('identification')) {
|
||||||
|
await sel.selectOption({ label: /prefer not|decline|do not wish|i don/i }).catch(async () => {
|
||||||
|
const opts = await sel.$$('option');
|
||||||
|
for (const opt of opts) {
|
||||||
|
const text = await opt.textContent();
|
||||||
|
if (/prefer not|decline|do not wish|i don/i.test(text || '')) {
|
||||||
|
await sel.selectOption({ label: text.trim() }).catch(() => {});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checkboxes — "mark as top choice" and similar opt-ins
|
||||||
|
for (const cb of await page.$$('input[type="checkbox"]')) {
|
||||||
|
if (!await cb.isVisible().catch(() => false)) continue;
|
||||||
|
if (await cb.isChecked().catch(() => false)) continue;
|
||||||
|
const lbl = await this.getLabel(cb);
|
||||||
|
const l = lbl.toLowerCase();
|
||||||
|
// Check opt-in boxes (top choice, interested, confirm)
|
||||||
|
if (l.includes('top choice') || l.includes('interested') || l.includes('confirm') || l.includes('agree')) {
|
||||||
|
await cb.check().catch(() => {});
|
||||||
|
}
|
||||||
|
// Skip EEO/legal checkboxes — leave unchecked unless they are required confirms
|
||||||
|
}
|
||||||
|
|
||||||
return unknown;
|
return unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user