refactor(clickTtPlayerRegistrationService): enhance application search and link handling
- Introduced a new function to normalize comparable text for improved matching during application searches. - Updated the _openApplicationAfterSearch method to accept member data, enhancing the accuracy of application link retrieval based on expected name and birth date. - Improved error handling to provide clearer feedback when no matching application entry is found, ensuring better user guidance during the registration process.
This commit is contained in:
@@ -37,6 +37,14 @@ function escapeRegExp(value) {
|
||||
return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
function normalizeComparableText(value) {
|
||||
return String(value || '')
|
||||
.normalize('NFKC')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
function buildDebugHtmlPath() {
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
return path.join(process.cwd(), 'tmp', `clicktt-debug-${timestamp}.html`);
|
||||
@@ -113,7 +121,7 @@ class ClickTtPlayerRegistrationService {
|
||||
await this._clickByText(page, 'Personen suchen', trace);
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
|
||||
await this._openApplicationAfterSearch(page, trace);
|
||||
await this._openApplicationAfterSearch(page, memberJson, trace);
|
||||
await this._fillApplicationForm(page, memberJson, primaryEmail, trace);
|
||||
await this._clickByText(page, 'Weiter >>', trace);
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
@@ -472,9 +480,41 @@ class ClickTtPlayerRegistrationService {
|
||||
}
|
||||
}
|
||||
|
||||
async _openApplicationAfterSearch(page, trace) {
|
||||
const explicitApplicationLink = page.getByText(/Spielberechtigung beantragen/i).first();
|
||||
if (await explicitApplicationLink.count()) {
|
||||
async _openApplicationAfterSearch(page, member, trace) {
|
||||
const expectedName = normalizeComparableText(`${member.lastName}, ${member.firstName}`);
|
||||
const expectedBirthDate = formatGermanDate(member.birthDate);
|
||||
|
||||
const explicitApplicationHref = await page.locator('table.result-set tr').evaluateAll((rows, criteria) => {
|
||||
const normalize = (value) => String(value || '')
|
||||
.normalize('NFKC')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
for (const row of rows) {
|
||||
const link = row.querySelector('a');
|
||||
const strong = row.querySelector('strong');
|
||||
const cells = Array.from(row.querySelectorAll('td'));
|
||||
const linkText = normalize(link?.textContent || '');
|
||||
const nameText = normalize(strong?.textContent || '');
|
||||
const birthDateText = normalize(cells[1]?.textContent || '');
|
||||
|
||||
if (!link || !strong) continue;
|
||||
if (!linkText.includes('spielberechtigung beantragen')) continue;
|
||||
if (nameText !== criteria.expectedName) continue;
|
||||
if (birthDateText !== normalize(criteria.expectedBirthDate)) continue;
|
||||
|
||||
return link.getAttribute('href');
|
||||
}
|
||||
|
||||
return null;
|
||||
}, {
|
||||
expectedName,
|
||||
expectedBirthDate
|
||||
});
|
||||
|
||||
if (explicitApplicationHref) {
|
||||
const explicitApplicationLink = page.locator(`a[href="${explicitApplicationHref}"]`).first();
|
||||
let dialogSeen = false;
|
||||
page.once('dialog', async (dialog) => {
|
||||
dialogSeen = true;
|
||||
@@ -488,7 +528,9 @@ class ClickTtPlayerRegistrationService {
|
||||
this._trace(trace, 'step', {
|
||||
name: 'click',
|
||||
label: 'Spielberechtigung beantragen',
|
||||
selector: 'text=/Spielberechtigung beantragen/i'
|
||||
selector: `a[href="${explicitApplicationHref}"]`,
|
||||
expectedName: `${member.lastName}, ${member.firstName}`,
|
||||
expectedBirthDate
|
||||
});
|
||||
await explicitApplicationLink.click();
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
@@ -501,12 +543,12 @@ class ClickTtPlayerRegistrationService {
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmLocator = page.locator('[onclick*="confirm("]').first();
|
||||
if (await confirmLocator.count()) {
|
||||
const text = sanitizePageText(
|
||||
await confirmLocator.innerText().catch(() => '') || await confirmLocator.getAttribute('value').catch(() => '') || ''
|
||||
const searchResultsText = sanitizePageText(await page.locator('table.result-set').innerText().catch(() => ''));
|
||||
if (searchResultsText) {
|
||||
throw new HttpError(
|
||||
`Kein exakt passender Click-TT-Sucheintrag für "${member.lastName}, ${member.firstName}" mit Geburtsdatum ${expectedBirthDate} gefunden`,
|
||||
409
|
||||
);
|
||||
throw new HttpError(`Click-TT-Suchergebnis mit Confirm gefunden, aber kein klickbares Antragselement per Label erkannt${text ? `: ${text}` : ''}`, 409);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user