diff --git a/app/Views/utenti/dettagli_utente.php b/app/Views/utenti/dettagli_utente.php index fc3dbf110..51a36cbae 100644 --- a/app/Views/utenti/dettagli_utente.php +++ b/app/Views/utenti/dettagli_utente.php @@ -35,9 +35,20 @@ 'standard' => __('Standard') ]; +$genderLabels = [ + 'M' => __('Maschio'), + 'F' => __('Femmina'), + 'Altro' => __('Altro'), +]; + +$sessoKey = trim((string)$sesso); +$sessoLabel = $genderLabels[$sessoKey] ?? $sessoKey; + $display = static function (?string $value, string $placeholder = '—'): string { $value = trim((string)$value); - return $value !== '' ? HtmlHelper::e($value) : $placeholder; + return $value !== '' + ? htmlspecialchars(HtmlHelper::decode($value), ENT_QUOTES, 'UTF-8') + : $placeholder; }; ?> @@ -147,7 +158,7 @@
-
+
diff --git a/tests/issue-255-registration.spec.js b/tests/issue-255-registration.spec.js index f49f3b31c..2fbad975e 100644 --- a/tests/issue-255-registration.spec.js +++ b/tests/issue-255-registration.spec.js @@ -1,6 +1,6 @@ // @ts-check /** - * Issue #255 — configurable registration fields. 29-check E2E suite. + * Issue #255 — configurable registration fields. 30-check E2E suite. * * Coverage (all through the real browser): * 1-4 defaults + SERVER-side enforcement of each built-in requirement @@ -18,7 +18,7 @@ * 23-24 sanitization: a tag-carrying label is neutralised on save; a * script-carrying VALUE is escaped when rendered back (admin detail). * 25 an inactive (attivo=0) field disappears from the public form. - * 26-29 profile/admin-detail regressions and destructive type-change guard. + * 26-30 profile/admin-detail regressions and destructive type-change guard. */ const { test, expect } = require('@playwright/test'); @@ -117,7 +117,7 @@ function userCount(email) { return Number(dbQuery(`SELECT COUNT(*) FROM utenti WHERE email='${email}'`)); } -test.describe.serial('Issue #255 — configurable registration fields (29 checks)', () => { +test.describe.serial('Issue #255 — configurable registration fields (30 checks)', () => { /** @type {import('@playwright/test').Page} */ let admin; /** @type {Map} setting key -> original HEX(setting_value) */ @@ -511,4 +511,32 @@ test.describe.serial('Issue #255 — configurable registration fields (29 checks expect(dbQuery(`SELECT tipo FROM registrazione_campi WHERE id=${id}`)).toBe('text'); await expect(admin.locator('body')).toContainText(/non puoi cambiare il tipo|cannot change the type|ne pouvez pas modifier le type|Typ eines Feldes/i); }); + + test('30. admin user details localize every stored sesso enum value', async ({ page }) => { + await setToggles(admin, false, false, false); + const email = `zz-255-sesso-${TOKEN}@example.test`; + await fillRegistration(page, { + fields: { nome: 'Sesso30', email, password: 'Password255!ok', password_confirm: 'Password255!ok' }, + }); + await page.selectOption('select[name="sesso"]', 'M'); + await submitNoValidate(page); + expect(userCount(email)).toBe(1); + + const uid = dbQuery(`SELECT id FROM utenti WHERE email='${email}'`); + expect(dbQuery(`SELECT sesso FROM utenti WHERE id=${uid}`)).toBe('M'); + + await admin.goto(`${BASE}/admin/users/edit/${uid}`); + /** @type {Record} */ + const expectedLabels = {}; + const genderValues = ['M', 'F', 'Altro']; + for (const value of genderValues) { + expectedLabels[value] = (await admin.locator(`select[name="sesso"] option[value="${value}"]`).innerText()).trim(); + } + + for (const value of genderValues) { + if (value !== 'M') dbQuery(`UPDATE utenti SET sesso='${value}' WHERE id=${uid}`); + await admin.goto(`${BASE}/admin/users/details/${uid}`); + await expect(admin.locator('[data-field="sesso"]')).toHaveText(expectedLabels[value]); + } + }); });