refactor(clickTtPlayerRegistrationService): enhance application form filling and consent handling

- Updated the _fillApplicationForm method to include trace logging and improved handling of form fields, ensuring all necessary data is filled correctly.
- Introduced a new method to check and fill empty fields, streamlining the form completion process.
- Added consent overlay dismissal to improve user experience during the registration flow.
This commit is contained in:
Torsten Schulz (local)
2026-03-11 16:31:23 +01:00
parent 6a18d4ce0f
commit c1cf903196

View File

@@ -107,9 +107,10 @@ class ClickTtPlayerRegistrationService {
await page.waitForLoadState('domcontentloaded');
await this._openApplicationAfterSearch(page, trace);
await this._fillApplicationForm(page, memberJson, primaryEmail);
await this._fillApplicationForm(page, memberJson, primaryEmail, trace);
await this._clickByText(page, 'Weiter >>', trace);
await page.waitForLoadState('domcontentloaded');
await this._dismissConsentOverlays(page, trace);
await this._clickByText(page, 'Speichern', trace);
await page.waitForLoadState('domcontentloaded');
await this._clickByText(page, 'Einreichen', trace);
@@ -390,27 +391,55 @@ class ClickTtPlayerRegistrationService {
await searchForm.locator('input[name$=".5"]').first().fill(formatGermanDate(member.birthDate));
}
async _fillApplicationForm(page, member, email) {
async _fillApplicationForm(page, member, email, trace) {
const form = page.locator('form.edit-object[enctype="multipart/form-data"]').first();
if (!(await form.count())) {
throw new HttpError('Click-TT-Antragsformular nicht gefunden', 500);
}
this._trace(trace, 'step', { name: 'fill-application-form' });
const birthDate = formatGermanDate(member.birthDate);
const textInputs = page.locator('input[type="text"]');
const inputCount = await textInputs.count();
await this._fillIfEmpty(form.locator('input[name$=".15"]').first(), member.lastName);
await this._fillIfEmpty(form.locator('input[name$=".17"]').first(), member.firstName);
await this._fillIfEmpty(form.locator('input[name$=".25"]').first(), birthDate);
await this._fillIfEmpty(form.locator('input[name$=".9"]').first(), member.street || '');
await this._fillIfEmpty(form.locator('input[name$=".15"]').nth(1), member.postalCode || '');
await this._fillIfEmpty(form.locator('input[name$=".17"]').nth(1), member.city || '');
await this._fillIfEmpty(form.locator('input[name$=".5"]').last(), email || '');
const fillIfEmpty = async (index, value) => {
if (!value || index >= inputCount) return;
const locator = textInputs.nth(index);
const currentValue = (await locator.inputValue().catch(() => '')).trim();
if (!currentValue) {
await locator.fill(value);
const nationalitySelect = form.locator('select[name$=".27"]').first();
if (await nationalitySelect.count()) {
const currentValue = await nationalitySelect.inputValue().catch(() => 'WONoSelectionString');
if (!currentValue || currentValue === 'WONoSelectionString') {
await nationalitySelect.selectOption({ label: /Deutschland/ });
}
};
}
await fillIfEmpty(0, member.lastName);
await fillIfEmpty(1, member.firstName);
await fillIfEmpty(3, birthDate);
await fillIfEmpty(5, member.street || '');
await fillIfEmpty(6, member.postalCode || '');
await fillIfEmpty(7, member.city || '');
await fillIfEmpty(13, email);
const countrySelect = form.locator('select[name$=".21.3"]').first();
if (await countrySelect.count()) {
const currentValue = await countrySelect.inputValue().catch(() => 'WONoSelectionString');
if (!currentValue || currentValue === 'WONoSelectionString') {
await countrySelect.selectOption({ label: /Deutschland/ });
}
}
const genderMap = {
female: 'input[id^="radioGenderFemale_"]',
male: 'input[id^="radioGenderMale_"]',
diverse: 'input[id^="radioGenderNonBinary_"]',
unknown: 'input[id^="radioGenderNotSpecified_"]'
};
const genderSelector = genderMap[member.gender] || genderMap.unknown;
const genderRadio = form.locator(genderSelector).first();
if (await genderRadio.count()) {
await genderRadio.check();
}
const dataPrivacyCheckbox = form.locator('input[type="checkbox"][name$=".45.3.2"]').first();
if (await dataPrivacyCheckbox.count()) {
await dataPrivacyCheckbox.check();
}
}
async _openApplicationAfterSearch(page, trace) {
@@ -472,6 +501,17 @@ class ClickTtPlayerRegistrationService {
return false;
}
async _fillIfEmpty(locator, value) {
if (!value || !(await locator.count())) {
return false;
}
const currentValue = (await locator.inputValue().catch(() => '')).trim();
if (!currentValue) {
await locator.fill(value);
}
return true;
}
async _hasTextTarget(page, text) {
const escaped = escapeRegExp(text);
const selectors = [