Refine subscription profile layout and focus handling
Build and Deploy Gateway / build-and-push (push) Successful in 19s
Build and Deploy Gateway / deploy (push) Successful in 7s

This commit is contained in:
2026-08-11 07:23:40 +03:00
parent 9432112fe2
commit af1c45e424
5 changed files with 139 additions and 87 deletions
@@ -50,8 +50,8 @@ test('local validation, scoped refresh and drawer focus remain feature-owned', (
assert.match(feature, /previousProfileCountRef\.current > 0\) setOpen\(false\)/);
assert.match(feature, /if \(!adding \|\| \(profiles\.length > 0 && !open\)\) return undefined/);
assert.match(feature, /if \(deleteIdRef\.current\) return;[\s\S]*toggleRef\.current\?\.focus\(\)/);
assert.match(feature, /const invoker = addInvokerRef\.current[\s\S]*if \(invoker\) requestAnimationFrame\(\(\) => invoker\.focus\(\)\)/);
assert.match(feature, /showAdd: \(\) => \{[\s\S]*addInvokerRef\.current = document\.activeElement instanceof HTMLElement/);
assert.match(feature, /setAdding\(false\)[\s\S]*client-profile-add-trigger'\)\?\.focus\(\)/);
assert.doesNotMatch(feature, /addInvokerRef/);
assert.match(feature, /function cancelRename\(\)[\s\S]*client-profile-menu-\$\{profileId\}[\s\S]*\.focus\(\)/);
assert.match(feature, /id=\{`client-profile-menu-\$\{profile\.id\}`\}/);
});
@@ -87,7 +87,8 @@ test('validation rejection parser preserves structured errors and normalizes non
test('feature keeps exact slots, truthy closes and subscription DOM order', () => {
assert.match(feature, /if \(!await onAdd\(normalizedLabel, normalizedUrl\)\) return;[\s\S]*resetAdd\(\)/);
assert.match(feature, /if \(!await onForget\(deleteProfile\.id, deleteStopsVpn \? 'stop-and-delete' : 'delete'\)\) return;[\s\S]*setDeleteId\(''\)/);
assert.match(feature, /client-profiles-operation[\s\S]*client-profiles-current[\s\S]*\{statusSlot\}[\s\S]*client-profile-list/);
assert.match(feature, /client-profiles-operation[\s\S]*\{statusSlot\}[\s\S]*client-profile-list[\s\S]*feature\.adding[\s\S]*AddProfileForm[\s\S]*client-profile-add-trigger/);
assert.doesNotMatch(feature, /client-profiles-current|aria-label="Добавить подписку"/);
assert.match(feature, /const drawerOpen = feature\.open && feature\.profiles\.length > 0/);
assert.match(feature, /feature\.profiles\.length === 0 && <div className="client-form client-subscription-first-run"/);
assert.match(page, /<SubscriptionPanel[\s\S]*statusSlot=\{<>[\s\S]*InlineError[\s\S]*renderServerPicker=[\s\S]*<ServerPicker/);
@@ -102,7 +103,8 @@ test('profiles render as flat accordion groups with scoped controls', () => {
assert.match(feature, /aria-expanded=\{expanded\}/);
assert.match(feature, /profile\.subscription\.status === 'stale'[\s\S]*profile\.subscription\.fetchedAt/);
assert.match(feature, /feature\.operations\.profileRefresh\?\.target === profile\.id/);
assert.match(feature, /const currentLabel = feature\.gatewayDirect[\s\S]*Gateway · сервер не определён/);
assert.match(feature, /!expanded && visibleServer && <button[\s\S]*client-profile-selected-server/);
assert.match(feature, /const visibleServerId = applied \? feature\.selection\.appliedServerId : profile\.desiredServerId/);
assert.match(feature, /const desired = !feature\.connected[\s\S]*&& !feature\.gatewayDirect/);
assert.match(styles, /\.client-profile-group/);
assert.match(styles, /\.client-profile-body/);