admin: fix the new-user username placeholder
All checks were successful
Build and Deploy to Production / test (push) Successful in 27s
Build and Deploy to Production / build (push) Successful in 1m2s
Build and Deploy to Production / deploy (push) Successful in 40s

The username field's attributes were emitted as one string through
<%= %>, which HTML-escapes the quotes, so the browser read the
placeholder as the literal "leave and dropped the rest. Write the
attributes in the template and test the rendered field.

Assisted-by: Claude:opus-5
This commit is contained in:
Sergei Poljanski 2026-10-10 09:17:39 +04:00
commit 7e262b8f89
Signed by: asxpi
GPG key ID: 4F8851660FA4121B
2 changed files with 10 additions and 1 deletions

View file

@ -49,6 +49,9 @@ class UsersAdminTest < Minitest::Test
def test_invite_without_username_lets_invitee_choose
admin_login!
get '/admin/users/new'
assert_includes last_response.body, 'placeholder="empty: the invitee picks one"' # not HTML-escaped into the attribute
refute_includes last_response.body, '&quot;'
create_user(username: '', perm: { 'bingo' => { 'read' => '1' } })
u = User.where(choose_username: true).first
assert_match(/\Ainvite-[0-9a-f]{8}\z/, u.username)

View file

@ -14,7 +14,13 @@
<input type="hidden" name="authenticity_token" value="<%= csrf_token %>" />
<fieldset class="plain" <%= 'disabled' unless editable %>>
<div class="invoice-grid">
<div class="field"><label for="username">Username<% if fresh %> <span class="optional">(optional)</span><% end %></label><input type="text" id="username" name="username" value="<%= @user.username %>" <%= fresh ? 'pattern=[a-z0-9][a-z0-9_.@-]{1,63} placeholder="leave empty: invitee chooses"' : (current_user.superuser ? 'required pattern=[a-z0-9][a-z0-9_.@-]{1,63}' : 'disabled') %> /></div>
<div class="field"><label for="username">Username<% if fresh %> <span class="optional">(optional)</span><% end %></label><% if fresh %>
<input type="text" id="username" name="username" value="<%= @user.username %>" pattern="[a-z0-9][a-z0-9_.@-]{1,63}" placeholder="empty: the invitee picks one" autocapitalize="none" />
<% elsif current_user.superuser %>
<input type="text" id="username" name="username" value="<%= @user.username %>" pattern="[a-z0-9][a-z0-9_.@-]{1,63}" required autocapitalize="none" />
<% else %>
<input type="text" id="username" name="username" value="<%= @user.username %>" disabled />
<% end %></div>
<div class="field"><label for="name">Name <span class="optional">(optional)</span></label><input type="text" id="name" name="name" value="<%= @user.name %>" /></div>
<div class="field"><label for="email">Email <span class="optional">(for invite and password reset)</span></label><input type="email" id="email" name="email" value="<%= @user.email %>" /></div>
</div>