fix: stuck detection uses progress bar value, not heading
Heading is always "Apply to <Company>" on every step — comparing it caused false stuck detection on step 2. Now: - Progress bar selector finds <progress> elements (no explicit role) - Stuck detection re-reads progress AFTER clicking Next to see if it changed - Threshold raised to 3 same-progress clicks before exiting Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -164,7 +164,6 @@ export async function apply(page, job, formFiller) {
|
||||
|
||||
// Step through modal
|
||||
let lastProgress = '-1';
|
||||
let lastHeading = '';
|
||||
let samePageCount = 0;
|
||||
for (let step = 0; step < LINKEDIN_MAX_MODAL_STEPS; step++) {
|
||||
const modalStillOpen = await page.$(MODAL);
|
||||
@@ -173,10 +172,10 @@ export async function apply(page, job, formFiller) {
|
||||
return { status: 'submitted', meta };
|
||||
}
|
||||
|
||||
// Read progress bar — use page.$() + evaluate on the handle
|
||||
const progressEl = await page.$(`${MODAL} [role="progressbar"]`);
|
||||
// Read progress bar — LinkedIn uses <progress> element (no explicit role="progressbar")
|
||||
const progressEl = await page.$(`${MODAL} progress, ${MODAL} [role="progressbar"]`);
|
||||
const progress = progressEl
|
||||
? await progressEl.evaluate(el => el.getAttribute('aria-valuenow') || el.getAttribute('value') || el.style?.width || '').catch(() => '')
|
||||
? await progressEl.evaluate(el => el.getAttribute('aria-valuenow') || el.value?.toString() || el.getAttribute('value') || el.style?.width || '').catch(() => '')
|
||||
: '';
|
||||
|
||||
// Debug snapshot using ElementHandle operations (shadow DOM safe)
|
||||
@@ -229,14 +228,18 @@ export async function apply(page, job, formFiller) {
|
||||
if (nextBtn) {
|
||||
console.log(` [step ${step}] clicking Next`);
|
||||
await nextBtn.click({ timeout: APPLY_CLICK_TIMEOUT }).catch(() => {});
|
||||
await page.waitForTimeout(CLICK_WAIT);
|
||||
|
||||
// Detect if we're stuck — same heading+progress means page didn't advance
|
||||
const curHeading = debugInfo.heading;
|
||||
if (curHeading === lastHeading && progress === lastProgress) {
|
||||
// Detect if we're stuck — wait for content to change after clicking Next
|
||||
await page.waitForTimeout(CLICK_WAIT);
|
||||
const newProgress = await (async () => {
|
||||
const el = await page.$(`${MODAL} progress, ${MODAL} [role="progressbar"]`);
|
||||
return el ? await el.evaluate(e => e.getAttribute('aria-valuenow') || e.value?.toString() || '').catch(() => '') : '';
|
||||
})();
|
||||
|
||||
if (newProgress === progress) {
|
||||
samePageCount++;
|
||||
if (samePageCount >= 2) {
|
||||
console.log(` [step ${step}] stuck — clicked Next but page didn't advance (${samePageCount} times)`);
|
||||
if (samePageCount >= 3) {
|
||||
console.log(` [step ${step}] stuck — clicked Next ${samePageCount} times but progress unchanged at ${progress}`);
|
||||
console.log(` Action: a required field may be unfilled. Check select dropdowns still at "Select an option"`);
|
||||
await dismissModal(page, MODAL);
|
||||
return { status: 'stuck', meta };
|
||||
@@ -244,8 +247,7 @@ export async function apply(page, job, formFiller) {
|
||||
} else {
|
||||
samePageCount = 0;
|
||||
}
|
||||
lastProgress = progress;
|
||||
lastHeading = curHeading;
|
||||
lastProgress = newProgress;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -259,7 +261,6 @@ export async function apply(page, job, formFiller) {
|
||||
await reviewBtn.click({ timeout: APPLY_CLICK_TIMEOUT }).catch(() => {});
|
||||
await page.waitForTimeout(CLICK_WAIT);
|
||||
lastProgress = progress;
|
||||
lastHeading = debugInfo.heading;
|
||||
samePageCount = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user