Fix submit verification: wait for modal detach instead of fixed sleep
Replace fixed 2.5s sleep + single check with event-driven waitForSelector (state: 'detached', timeout: 8s). If modal persists, check for success indicators (success text, Submit button gone) before marking incomplete. Fixes false 'incomplete' status when LinkedIn shows post-submit dialog. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -273,20 +273,72 @@ export async function apply(page, job, formFiller) {
|
||||
if (submitBtn) {
|
||||
console.log(` [step ${step}] clicking Submit`);
|
||||
await submitBtn.click({ timeout: APPLY_CLICK_TIMEOUT }).catch(() => {});
|
||||
await page.waitForTimeout(SUBMIT_WAIT);
|
||||
|
||||
// Verify modal closed
|
||||
const modalGone = !(await page.$(MODAL));
|
||||
if (modalGone) {
|
||||
// Wait for modal to close — LinkedIn may take a few seconds after submit
|
||||
const modalClosed = await page.waitForSelector(MODAL, { state: 'detached', timeout: 8000 }).then(() => true).catch(() => false);
|
||||
if (modalClosed) {
|
||||
console.log(` ✅ Submit confirmed — modal closed`);
|
||||
return { status: 'submitted', meta };
|
||||
}
|
||||
|
||||
// Modal still open — submit may have failed
|
||||
console.log(` [step ${step}] ⚠️ Modal still open after Submit click`);
|
||||
console.log(` Action: submit may have failed due to validation or network error`);
|
||||
await dismissModal(page, MODAL);
|
||||
return { status: 'incomplete', meta };
|
||||
// Modal still open — LinkedIn often shows a post-submit confirmation/success
|
||||
// dialog that still matches [role="dialog"]. Check for success indicators.
|
||||
const postSubmitModal = await page.$(MODAL);
|
||||
if (postSubmitModal) {
|
||||
const postSubmitInfo = await postSubmitModal.evaluate(el => {
|
||||
const text = (el.innerText || el.textContent || '').toLowerCase();
|
||||
return {
|
||||
hasSuccess: text.includes('application was sent') || text.includes('applied') ||
|
||||
text.includes('thank you') || text.includes('submitted') ||
|
||||
text.includes('application has been') || text.includes('successfully'),
|
||||
hasDone: text.includes('done') || text.includes('got it'),
|
||||
snippet: (el.innerText || '').trim().slice(0, 200),
|
||||
};
|
||||
}).catch(() => ({ hasSuccess: false, hasDone: false, snippet: '' }));
|
||||
|
||||
console.log(` [step ${step}] post-submit modal: "${postSubmitInfo.snippet}"`);
|
||||
|
||||
if (postSubmitInfo.hasSuccess || postSubmitInfo.hasDone) {
|
||||
console.log(` ✅ Submit confirmed — success dialog detected`);
|
||||
// Try to dismiss the success dialog
|
||||
const doneBtn = await findModalButton(page, MODAL, {
|
||||
ariaLabels: ['Dismiss', 'Done', 'Close'],
|
||||
exactTexts: ['Done', 'Got it', 'Close'],
|
||||
});
|
||||
if (doneBtn) await doneBtn.click().catch(() => {});
|
||||
return { status: 'submitted', meta };
|
||||
}
|
||||
|
||||
// Check for validation errors — real failure
|
||||
const postErrors = await postSubmitModal.$$('[class*="error"], [aria-invalid="true"], .artdeco-inline-feedback--error');
|
||||
const errorTexts = [];
|
||||
for (const e of postErrors) {
|
||||
const t = await e.evaluate(el => el.textContent?.trim()?.slice(0, 80) || '').catch(() => '');
|
||||
if (t) errorTexts.push(t);
|
||||
}
|
||||
|
||||
if (errorTexts.length > 0) {
|
||||
console.log(` [step ${step}] ❌ Validation errors after Submit: ${JSON.stringify(errorTexts)}`);
|
||||
await dismissModal(page, MODAL);
|
||||
return { status: 'incomplete', meta, validation_errors: errorTexts };
|
||||
}
|
||||
|
||||
// No errors, no success text — but Submit button is gone, likely succeeded
|
||||
// (LinkedIn sometimes shows a follow-up prompt like "Follow company?")
|
||||
const submitStillThere = await findModalButton(page, MODAL, {
|
||||
ariaLabels: ['Submit application'],
|
||||
exactTexts: ['Submit application'],
|
||||
});
|
||||
if (!submitStillThere) {
|
||||
console.log(` ✅ Submit likely succeeded — Submit button gone, no errors`);
|
||||
await dismissModal(page, MODAL);
|
||||
return { status: 'submitted', meta };
|
||||
}
|
||||
|
||||
console.log(` [step ${step}] ⚠️ Submit button still present — click may not have registered`);
|
||||
await dismissModal(page, MODAL);
|
||||
return { status: 'incomplete', meta };
|
||||
}
|
||||
}
|
||||
|
||||
// Stuck detection — no Next/Review/Submit found
|
||||
|
||||
Reference in New Issue
Block a user