fix(import): consistent add-source forms with masked passwords and URL errors

- Mask the Xtream password in add and edit (and the Stalker one in edit)
  behind a shared PasswordVisibilityToggleDirective: one translated
  "Show password" label, state in aria-pressed, type="button".
- Give the Xtream server URL its own mat-error and a neutral hint instead
  of the EPG file error; give the M3U URL a mat-error.
- Use "Playlist title" in every add form, "MAC address" casing, a single
  ellipsis in "Validating portal…" and one "Add playlist" submit label;
  translate the method radiogroup's aria-label.
- Show Stalker refusals inline under the portal URL (role="status", like
  the Xtream connection test), translated in the template and cleared by
  edits; translate the snackbars for outcomes that close the dialog.
- Translate new strings into all locales; reuse the identical Stalker URL
  error translations; fix MAC casing and ellipses; drop unused keys.
- Unit specs per form, edit-dialog spec, new add-source-forms web E2E;
  update E2E locators; UI guidelines Forms section; Stalker contract.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-10-03 09:55:16 +02:00
1 parent 23a1860119
commit 0ea9ecdb27
56 files changed
+1208 -252

No files matched your search

+4 -1
View File
@@ -462,7 +462,10 @@ async function addStalkerPortal(page: Page): Promise<void> {
await dialog.locator('#portalUrl').fill(STALKER_FIXTURE_PORTAL_URL);
await dialog.locator('#macAddress').fill(STALKER_FIXTURE_MAC);
// Endpoint discovery probes the mock before the row is written.
await dialog.getByRole('button', { name: /^add$/i }).last().click();
await dialog
.getByRole('button', { name: /^(add|add playlist)$/i })
.last()
.click();
await dialog.waitFor({ state: 'detached', timeout: 60_000 });
await page.waitForURL(/\/workspace\/stalker\/[^/]+\/vod/, {
timeout: 60_000,