Skip to content

Commit 6410319

Browse files
committed
Test fixes
1 parent 20eaed4 commit 6410319

9 files changed

Lines changed: 97 additions & 68 deletions

File tree

app/lib/primer/forms/caption.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<% if @input.character_limit? %>
2-
<span class="sr-only" data-target="<%= @input.character_limit_target_prefix %>.characterLimitSrElement" id="<%= @input.character_limit_sr_id %>" aria-live="polite" aria-atomic="true"></span>
2+
<span class="sr-only" data-target="<%= @input.character_limit_target_prefix %>.characterLimitSrElement" aria-live="polite" aria-atomic="true"></span>
33
<span class="FormControl-caption" data-target="<%= @input.character_limit_target_prefix %>.characterLimitElement" data-max-length="<%= @input.character_limit %>" id="<%= @input.character_limit_id %>">
44
<span class="FormControl-caption-icon" hidden><%= render(Primer::Beta::Octicon.new(icon: :"alert-fill", size: :xsmall, aria: { hidden: true })) %></span>
55
<span class="FormControl-caption-text"><%= @input.character_limit %> <%= @input.character_limit == 1 ? 'character' : 'characters' %> remaining</span>

app/lib/primer/forms/character_counter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export class CharacterCounter {
1010
constructor(
1111
private inputElement: HTMLInputElement | HTMLTextAreaElement,
1212
private characterLimitElement: HTMLElement,
13-
private characterLimitSrElement?: HTMLElement,
13+
private characterLimitSrElement: HTMLElement,
1414
) {}
1515

1616
/**

app/lib/primer/forms/dsl/text_area_input.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ def character_limit?
3333
@character_limit.present?
3434
end
3535

36-
def character_limit_sr_id
37-
@character_limit_sr_id ||= "#{name}-character-count-sr-#{SecureRandom.hex(4)}"
38-
end
39-
4036
# :nocov:
4137
def focusable?
4238
true

app/lib/primer/forms/dsl/text_field_input.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,6 @@ def character_limit?
7676
@character_limit.present?
7777
end
7878

79-
def character_limit_sr_id
80-
@character_limit_sr_id ||= "#{name}-character-count-sr-#{SecureRandom.hex(4)}"
81-
end
82-
8379
def validation_arguments
8480
if auto_check_src.present?
8581
super.merge(

test/lib/primer/forms/form_control_test.rb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,11 @@ def test_character_limit_generates_aria_live_region
6565
end
6666

6767
# Aria-live region exists and is configured correctly
68-
assert_selector "span.sr-only[aria-live='polite']" do |element|
69-
assert element["id"].start_with?("username-character-count-sr-")
70-
# Should be empty initially (populated by JS)
68+
assert_selector "span.sr-only[data-target='primer-text-field.characterLimitSrElement'][aria-live='polite']" do |element|
7169
assert_equal "", element.text.strip
7270
end
7371

74-
assert_selector "span.FormControl-caption[data-max-length='50']", text: "50 characters remaining."
72+
assert_selector "span.FormControl-caption[data-max-length='50'] .FormControl-caption-text", text: "50 characters remaining"
7573
end
7674

7775
def test_character_limit_works_with_text_area
@@ -100,8 +98,8 @@ def test_character_limit_with_caption_shows_both
10098
end
10199
end
102100

103-
# Both caption text and character limit are present
101+
# Both caption text and character limit are present (as separate spans)
104102
assert_selector "span.FormControl-caption", text: "Keep it short and descriptive"
105-
assert_selector "span.FormControl-caption[data-max-length='100']", text: "100 characters remaining."
103+
assert_selector "span.FormControl-caption[data-max-length='100'] .FormControl-caption-text", text: "100 characters remaining"
106104
end
107105
end

test/lib/primer/forms/text_area_input_test.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,9 @@ def test_renders_character_limit_form
4141
end
4242

4343
assert_selector "primer-text-area"
44-
assert_selector "span.FormControl-caption[data-target='primer-text-area.characterLimitElement'][data-max-length='100']", text: "100 characters remaining."
44+
assert_selector "span.FormControl-caption[data-target='primer-text-area.characterLimitElement'][data-max-length='100'] .FormControl-caption-text", text: "100 characters remaining"
4545
assert_selector "textarea[data-target='primer-text-area.inputElement']"
46-
assert_selector "span.sr-only[aria-live='polite']" do |span|
47-
assert span["id"].start_with?("bio-character-count-sr-")
48-
end
46+
assert_selector "span.sr-only[data-target='primer-text-area.characterLimitSrElement'][aria-live='polite']"
4947
end
5048

5149
def test_character_limit_rejects_zero
@@ -85,7 +83,7 @@ def test_character_limit_with_caption
8583
end
8684
end
8785

88-
assert_selector "span.FormControl-caption[data-max-length='100']", text: "100 characters remaining."
86+
assert_selector "span.FormControl-caption[data-max-length='100'] .FormControl-caption-text", text: "100 characters remaining"
8987
assert_selector "span.FormControl-caption", text: "Tell us about yourself"
9088
end
9189
end

test/lib/primer/forms/text_field_input_test.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,9 @@ def test_renders_character_limit_form
6969
end
7070

7171
assert_selector "primer-text-field"
72-
assert_selector "span.FormControl-caption[data-max-length='20']", text: "20 characters remaining."
72+
assert_selector "span.FormControl-caption[data-max-length='20'] .FormControl-caption-text", text: "20 characters remaining"
7373
assert_selector "input[type=text][data-target*='primer-text-field.inputElement']"
74-
assert_selector "span.sr-only[aria-live='polite']" do |span|
75-
assert span["id"].start_with?("username-character-count-sr-")
76-
end
74+
assert_selector "span.sr-only[data-target='primer-text-field.characterLimitSrElement'][aria-live='polite']"
7775
end
7876

7977
def test_character_limit_rejects_zero
@@ -113,7 +111,7 @@ def test_character_limit_with_caption
113111
end
114112
end
115113

116-
assert_selector "span.FormControl-caption[data-max-length='20']", text: "20 characters remaining."
114+
assert_selector "span.FormControl-caption[data-max-length='20'] .FormControl-caption-text", text: "20 characters remaining"
117115
assert_selector "span.FormControl-caption", text: "Choose a unique username"
118116
end
119117
end

test/system/alpha/text_area_test.rb

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ class IntegrationTextAreaTest < System::TestCase
99
def test_character_limit_updates_on_input
1010
visit_preview(:with_character_limit)
1111

12-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "10 characters remaining."
13-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-area.validationElement']", visible: :hidden
12+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "10 characters remaining"
13+
refute_selector "span.FormControl-caption .FormControl-caption-icon[hidden]", visible: :all
1414

1515
textarea = find("textarea[data-target='primer-text-area.inputElement']")
1616
textarea.fill_in(with: "Hello")
1717

1818
sleep 0.3
1919

20-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "5 characters remaining."
21-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-area.validationElement']", visible: :hidden
20+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "5 characters remaining"
21+
refute_selector "span.FormControl-caption .FormControl-caption-icon[hidden]", visible: :all
2222
end
2323

2424
def test_character_limit_shows_validation_when_exceeded
@@ -29,18 +29,11 @@ def test_character_limit_shows_validation_when_exceeded
2929

3030
sleep 0.3
3131

32-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "2 characters over."
33-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-area.validationElement']", visible: :visible do |element|
34-
assert_includes element.text, "You've exceeded the character limit"
35-
end
32+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "2 characters over"
33+
assert_selector "span.FormControl-caption .FormControl-caption-icon:not([hidden])", visible: :visible
34+
assert_selector "span.FormControl-caption.fgColor-danger"
3635

3736
assert_selector "textarea[invalid='true'][aria-invalid='true']"
38-
39-
validation_element = find("div.FormControl-inlineValidation[data-target='primer-text-area.validationElement']")
40-
validation_id = validation_element["id"]
41-
42-
textarea_aria_describedby = textarea["aria-describedby"]
43-
assert_includes textarea_aria_describedby, validation_id, "textarea aria-describedby should include validation element ID"
4437
end
4538

4639
def test_character_limit_clears_validation_when_back_under_limit
@@ -50,14 +43,15 @@ def test_character_limit_clears_validation_when_back_under_limit
5043
textarea.fill_in(with: "Hello World!") # 12 characters
5144
sleep 0.3
5245

53-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-area.validationElement']", visible: :visible
46+
assert_selector "span.FormControl-caption .FormControl-caption-icon:not([hidden])", visible: :visible
5447
assert_selector "textarea[invalid='true'][aria-invalid='true']"
5548

5649
textarea.fill_in(with: "Hello") # 5 characters
5750
sleep 0.3
5851

59-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "5 characters remaining."
60-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-area.validationElement']", visible: :hidden
52+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "5 characters remaining"
53+
refute_selector "span.FormControl-caption .FormControl-caption-icon[hidden]", visible: :all
54+
refute_selector "span.FormControl-caption.fgColor-danger"
6155

6256
refute_selector "textarea[invalid='true']"
6357
refute_selector "textarea[aria-invalid='true']"
@@ -74,12 +68,12 @@ def test_character_limit_screen_reader_text_updates
7468
# Wait for debounced update (500ms + buffer)
7569
sleep 0.6
7670

77-
assert_equal "6 characters remaining.", sr_element.text
71+
assert_equal "6 characters remaining", sr_element.text
7872

7973
textarea.fill_in(with: "Hello World!") # 12 characters
8074
sleep 0.6
8175

82-
assert_equal "2 characters over.", sr_element.text
76+
assert_equal "2 characters over", sr_element.text
8377
end
8478

8579
def test_character_limit_singular_vs_plural
@@ -89,12 +83,53 @@ def test_character_limit_singular_vs_plural
8983
textarea.fill_in(with: "123456789") # 9 characters, limit is 10
9084
sleep 0.3
9185

92-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "1 character remaining."
86+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "1 character remaining"
9387

9488
textarea.fill_in(with: "12345678901") # 11 characters
9589
sleep 0.3
9690

97-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "1 character over."
91+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "1 character over"
92+
end
93+
94+
def test_character_limit_screen_reader_not_announced_on_load
95+
visit_preview(:with_character_limit)
96+
97+
sr_element = find("span.sr-only[aria-live='polite']")
98+
99+
# Screen reader element should be empty on initial load
100+
assert_equal "", sr_element.text
101+
102+
# Only populated after user input
103+
textarea = find("textarea[data-target='primer-text-area.inputElement']")
104+
textarea.fill_in(with: "Test")
105+
106+
sleep 0.6 # Wait for debounced update
107+
108+
assert_equal "6 characters remaining", sr_element.text
109+
end
110+
111+
def test_character_limit_icon_visibility
112+
visit_preview(:with_character_limit)
113+
114+
# Icon should be hidden initially
115+
assert_selector "span.FormControl-caption .FormControl-caption-icon[hidden]"
116+
117+
textarea = find("textarea[data-target='primer-text-area.inputElement']")
118+
119+
# Icon should remain hidden when under limit
120+
textarea.fill_in(with: "Hello")
121+
sleep 0.3
122+
assert_selector "span.FormControl-caption .FormControl-caption-icon[hidden]"
123+
124+
# Icon should be visible when over limit
125+
textarea.fill_in(with: "Hello World!")
126+
sleep 0.3
127+
assert_selector "span.FormControl-caption .FormControl-caption-icon:not([hidden])", visible: :visible
128+
129+
# Icon should be hidden again when back under limit
130+
textarea.fill_in(with: "Hi")
131+
sleep 0.3
132+
assert_selector "span.FormControl-caption .FormControl-caption-icon[hidden]"
98133
end
99134
end
100135
end

test/system/alpha/text_field_test.rb

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,16 @@ def test_shows_and_hides_screenreader_text
120120
def test_character_limit_updates_on_input
121121
visit_preview(:with_character_limit)
122122

123-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "10 characters remaining."
124-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-field.characterLimitValidationElement']", visible: :hidden
123+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "10 characters remaining"
124+
refute_selector "span.FormControl-caption .FormControl-caption-icon[hidden]", visible: :all
125125

126126
input = find("input[type=text][data-target*='primer-text-field.inputElement']")
127127
input.fill_in(with: "Hello")
128128

129129
sleep 0.2
130130

131-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "5 characters remaining."
132-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-field.characterLimitValidationElement']", visible: :hidden
131+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "5 characters remaining"
132+
refute_selector "span.FormControl-caption .FormControl-caption-icon[hidden]", visible: :all
133133
end
134134

135135
def test_character_limit_shows_validation_when_exceeded
@@ -141,17 +141,10 @@ def test_character_limit_shows_validation_when_exceeded
141141

142142
sleep 0.3
143143

144-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "2 characters over."
145-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-field.characterLimitValidationElement']", visible: :visible do |element|
146-
assert_includes element.text, "You've exceeded the character limit"
147-
end
144+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "2 characters over"
145+
assert_selector "span.FormControl-caption .FormControl-caption-icon:not([hidden])", visible: :visible
146+
assert_selector "span.FormControl-caption.fgColor-danger"
148147
assert_selector "input[invalid='true'][aria-invalid='true']"
149-
150-
validation_element = find("div.FormControl-inlineValidation[data-target='primer-text-field.characterLimitValidationElement']")
151-
validation_id = validation_element["id"]
152-
153-
input_aria_describedby = input["aria-describedby"]
154-
assert_includes input_aria_describedby, validation_id, "input aria-describedby should include validation element ID"
155148
end
156149

157150
def test_character_limit_clears_validation_when_back_under_limit
@@ -162,14 +155,15 @@ def test_character_limit_clears_validation_when_back_under_limit
162155
input.fill_in(with: "Hello World!") # 12 characters
163156
sleep 0.3
164157

165-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-field.characterLimitValidationElement']", visible: :visible
158+
assert_selector "span.FormControl-caption .FormControl-caption-icon:not([hidden])", visible: :visible
166159
assert_selector "input[invalid='true'][aria-invalid='true']"
167160

168161
input.fill_in(with: "Hello") # 5 characters
169162
sleep 0.3
170163

171-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "5 characters remaining."
172-
assert_selector "div.FormControl-inlineValidation[data-target='primer-text-field.characterLimitValidationElement']", visible: :hidden
164+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "5 characters remaining"
165+
refute_selector "span.FormControl-caption .FormControl-caption-icon[hidden]", visible: :all
166+
refute_selector "span.FormControl-caption.fgColor-danger"
173167

174168
refute_selector "input[invalid='true']"
175169
refute_selector "input[aria-invalid='true']"
@@ -187,12 +181,12 @@ def test_character_limit_screen_reader_text_updates
187181
# Wait for debounced update (500ms + buffer)
188182
sleep 0.6
189183

190-
assert_equal "6 characters remaining.", sr_element.text
184+
assert_equal "6 characters remaining", sr_element.text
191185

192186
input.fill_in(with: "Hello World!") # 12 characters
193187
sleep 0.6
194188

195-
assert_equal "2 characters over.", sr_element.text
189+
assert_equal "2 characters over", sr_element.text
196190
end
197191

198192
def test_character_limit_singular_vs_plural
@@ -203,12 +197,26 @@ def test_character_limit_singular_vs_plural
203197
input.fill_in(with: "123456789") # 9 characters, limit is 10
204198
sleep 0.3
205199

206-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "1 character remaining."
200+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "1 character remaining"
207201

208202
input.fill_in(with: "12345678901") # 11 characters
209203
sleep 0.3
210204

211-
assert_selector "span.FormControl-caption[data-max-length='10']", text: "1 character over."
205+
assert_selector "span.FormControl-caption[data-max-length='10'] .FormControl-caption-text", text: "1 character over"
206+
end
207+
208+
def test_character_limit_screen_reader_not_announced_on_load
209+
visit_preview(:with_character_limit)
210+
211+
sr_element = find("span.sr-only[aria-live='polite']")
212+
213+
assert_equal "", sr_element.text
214+
215+
input = find("input[type=text][data-target*='primer-text-field.inputElement']")
216+
input.fill_in(with: "Test")
217+
218+
sleep 0.6 # Wait for debounced update
219+
assert_equal "6 characters remaining", sr_element.text
212220
end
213221
end
214222
end

0 commit comments

Comments
 (0)