|
6 | 6 | <script> |
7 | 7 | 'use strict'; |
8 | 8 |
|
9 | | -// Verifies that FormControlRange updates its start/end offsets for |
| 9 | +// Verifies that OpaqueRange updates its start/end offsets for |
10 | 10 | // programmatic text mutations mirroring DOM Range behavior in the control’s |
11 | 11 | // value space. Each test first exercises a DOM Range in a contenteditable div, |
12 | | -// then performs the equivalent operation with FormControlRange to ensure |
| 12 | +// then performs the equivalent operation with OpaqueRange to ensure |
13 | 13 | // behavior parity. |
14 | 14 |
|
15 | 15 | const controls = ['input', 'textarea']; |
|
49 | 49 | assert_equals(domRange1.startOffset, 0, 'DOM shorter: start collapsed to 0'); |
50 | 50 | assert_equals(domRange1.endOffset, 0, 'DOM shorter: end collapsed to 0'); |
51 | 51 |
|
52 | | - // FormControlRange: full .value replacement (shorter) collapses to [0,0]. |
| 52 | + // OpaqueRange: full .value replacement (shorter) collapses to [0,0]. |
53 | 53 | let element = setup(control, 'ABCDEFG'); |
54 | 54 | let range = element.getValueRange(2, 5); |
55 | 55 | element.value = 'XY'; |
56 | | - assert_equals(range.startOffset, 0, 'FormControlRange shorter: start collapsed to 0'); |
57 | | - assert_equals(range.endOffset, 0, 'FormControlRange shorter: end collapsed to 0'); |
| 56 | + assert_equals(range.startOffset, 0, 'OpaqueRange shorter: start collapsed to 0'); |
| 57 | + assert_equals(range.endOffset, 0, 'OpaqueRange shorter: end collapsed to 0'); |
58 | 58 |
|
59 | 59 | // DOM: full replace (longer) collapses to [0,0]. |
60 | 60 | const d2 = setupEditable('ABC'); |
|
63 | 63 | assert_equals(domRange2.startOffset, 0, 'DOM longer: start collapsed to 0'); |
64 | 64 | assert_equals(domRange2.endOffset, 0, 'DOM longer: end collapsed to 0'); |
65 | 65 |
|
66 | | - // FormControlRange: full .value replacement (longer) collapses to [0,0]. |
| 66 | + // OpaqueRange: full .value replacement (longer) collapses to [0,0]. |
67 | 67 | element = setup(control, 'ABC'); |
68 | 68 | range = element.getValueRange(1, 3); |
69 | 69 | element.value = 'ABCDEFGHIJKLMNOP'; |
70 | | - assert_equals(range.startOffset, 0, 'FormControlRange longer: start collapsed to 0'); |
71 | | - assert_equals(range.endOffset, 0, 'FormControlRange longer: end collapsed to 0'); |
| 70 | + assert_equals(range.startOffset, 0, 'OpaqueRange longer: start collapsed to 0'); |
| 71 | + assert_equals(range.endOffset, 0, 'OpaqueRange longer: end collapsed to 0'); |
72 | 72 | }, `Full replace collapses to start (shorter & longer) (${control})`); |
73 | 73 |
|
74 | 74 | test(() => { |
|
79 | 79 | assert_equals(domRange.startOffset, 0, 'DOM whole-old: start collapsed to 0'); |
80 | 80 | assert_equals(domRange.endOffset, 0, 'DOM whole-old: end collapsed to 0'); |
81 | 81 |
|
82 | | - // FormControlRange: same scenario. |
| 82 | + // OpaqueRange: same scenario. |
83 | 83 | const element = setup(control, 'ABCDE'); |
84 | 84 | const range = element.getValueRange(0, 5); |
85 | 85 | element.value = 'VWXYZ'; |
86 | | - assert_equals(range.startOffset, 0, 'FormControlRange whole-old: start collapsed to 0'); |
87 | | - assert_equals(range.endOffset, 0, 'FormControlRange whole-old: end collapsed to 0'); |
| 86 | + assert_equals(range.startOffset, 0, 'OpaqueRange whole-old: start collapsed to 0'); |
| 87 | + assert_equals(range.endOffset, 0, 'OpaqueRange whole-old: end collapsed to 0'); |
88 | 88 | }, `Full replace from whole-old range collapses to 0 (${control})`); |
89 | 89 |
|
90 | 90 | test(() => { |
|
95 | 95 | assert_equals(domRange.startOffset, 0, 'DOM equal-length: start collapsed to 0'); |
96 | 96 | assert_equals(domRange.endOffset, 0, 'DOM equal-length: end collapsed to 0'); |
97 | 97 |
|
98 | | - // FormControlRange: same scenario. |
| 98 | + // OpaqueRange: same scenario. |
99 | 99 | const element = setup(control, 'ABCDE'); |
100 | 100 | const range = element.getValueRange(1, 4); |
101 | 101 | element.value = 'VWXYZ'; |
102 | | - assert_equals(range.startOffset, 0, 'FormControlRange equal-length: start collapsed to 0'); |
103 | | - assert_equals(range.endOffset, 0, 'FormControlRange equal-length: end collapsed to 0'); |
| 102 | + assert_equals(range.startOffset, 0, 'OpaqueRange equal-length: start collapsed to 0'); |
| 103 | + assert_equals(range.endOffset, 0, 'OpaqueRange equal-length: end collapsed to 0'); |
104 | 104 | }, `Full replace (equal length) collapses to 0 (${control})`); |
105 | 105 |
|
106 | 106 | test(() => { |
|
112 | 112 | assert_equals(domRange.startOffset, 2, 'DOM start unchanged before replaced segment'); |
113 | 113 | assert_equals(domRange.endOffset, 6, 'DOM end adjusted by net delta'); |
114 | 114 |
|
115 | | - // FormControlRange: same replace via setRangeText. |
| 115 | + // OpaqueRange: same replace via setRangeText. |
116 | 116 | const element = setup(control, '0123456789'); |
117 | 117 | const range = element.getValueRange(2, 8); |
118 | 118 | element.setRangeText('XX', 3, 7); |
119 | | - assert_equals(element.value, '012XX789', 'FormControlRange value reflects setRangeText replace'); |
120 | | - assert_equals(range.startOffset, 2, 'FormControlRange start unchanged before replaced segment'); |
121 | | - assert_equals(range.endOffset, 6, 'FormControlRange end adjusted by net delta'); |
| 119 | + assert_equals(element.value, '012XX789', 'OpaqueRange value reflects setRangeText replace'); |
| 120 | + assert_equals(range.startOffset, 2, 'OpaqueRange start unchanged before replaced segment'); |
| 121 | + assert_equals(range.endOffset, 6, 'OpaqueRange end adjusted by net delta'); |
122 | 122 | }, `Partial replacement adjusts end (${control})`); |
123 | 123 |
|
124 | 124 | test(() => { |
|
128 | 128 | assert_equals(domRange.startOffset, 1, 'DOM start unchanged on no-op'); |
129 | 129 | assert_equals(domRange.endOffset, 4, 'DOM end unchanged on no-op'); |
130 | 130 |
|
131 | | - // FormControlRange: setting same value (no-op); range unchanged. |
| 131 | + // OpaqueRange: setting same value (no-op); range unchanged. |
132 | 132 | const element = setup(control, 'HELLO'); |
133 | 133 | const range = element.getValueRange(1, 4); |
134 | 134 | element.value = 'HELLO'; |
135 | | - assert_equals(range.startOffset, 1, 'FormControlRange start unchanged on no-op'); |
136 | | - assert_equals(range.endOffset, 4, 'FormControlRange end unchanged on no-op'); |
| 135 | + assert_equals(range.startOffset, 1, 'OpaqueRange start unchanged on no-op'); |
| 136 | + assert_equals(range.endOffset, 4, 'OpaqueRange end unchanged on no-op'); |
137 | 137 | }, `No-op leaves range unchanged (${control})`); |
138 | 138 |
|
139 | 139 | test(() => { |
|
145 | 145 | assert_equals(domRange.startOffset, 3, 'DOM start +1'); |
146 | 146 | assert_equals(domRange.endOffset, 5, 'DOM end +1'); |
147 | 147 |
|
148 | | - // FormControlRange: same insert via setRangeText. |
| 148 | + // OpaqueRange: same insert via setRangeText. |
149 | 149 | const element = setup(control, 'ABCDE'); |
150 | 150 | const range = element.getValueRange(2, 4); |
151 | 151 | element.setRangeText('Q', 1, 1); |
152 | | - assert_equals(element.value, 'AQBCDE', 'FormControlRange value after insertion before range'); |
153 | | - assert_equals(range.startOffset, 3, 'FormControlRange start +1'); |
154 | | - assert_equals(range.endOffset, 5, 'FormControlRange end +1'); |
| 152 | + assert_equals(element.value, 'AQBCDE', 'OpaqueRange value after insertion before range'); |
| 153 | + assert_equals(range.startOffset, 3, 'OpaqueRange start +1'); |
| 154 | + assert_equals(range.endOffset, 5, 'OpaqueRange end +1'); |
155 | 155 | }, `Insertion before range shifts both endpoints (${control})`); |
156 | 156 |
|
157 | 157 | test(() => { |
|
163 | 163 | assert_equals(domRange.startOffset, 1, 'DOM start unchanged'); |
164 | 164 | assert_equals(domRange.endOffset, 4, 'DOM end -1'); |
165 | 165 |
|
166 | | - // FormControlRange: same delete via setRangeText. |
| 166 | + // OpaqueRange: same delete via setRangeText. |
167 | 167 | const element = setup(control, 'ABCDE'); |
168 | 168 | const range = element.getValueRange(1, 5); |
169 | 169 | element.setRangeText('', 2, 3); |
170 | | - assert_equals(element.value, 'ABDE', 'FormControlRange value after interior deletion'); |
171 | | - assert_equals(range.startOffset, 1, 'FormControlRange start unchanged'); |
172 | | - assert_equals(range.endOffset, 4, 'FormControlRange end -1'); |
| 170 | + assert_equals(element.value, 'ABDE', 'OpaqueRange value after interior deletion'); |
| 171 | + assert_equals(range.startOffset, 1, 'OpaqueRange start unchanged'); |
| 172 | + assert_equals(range.endOffset, 4, 'OpaqueRange end -1'); |
173 | 173 | }, `Interior deletion shrinks end (${control})`); |
174 | 174 |
|
175 | 175 | test(() => { |
|
181 | 181 | assert_equals(domRange.startOffset, 5, 'DOM start -2'); |
182 | 182 | assert_equals(domRange.endOffset, 8, 'DOM end -2'); |
183 | 183 |
|
184 | | - // FormControlRange: same replacement via setRangeText. |
| 184 | + // OpaqueRange: same replacement via setRangeText. |
185 | 185 | const element = setup(control, 'ABCDEFGHIJ'); |
186 | 186 | const range = element.getValueRange(7, 10); |
187 | 187 | element.setRangeText('Z', 2, 5); |
188 | | - assert_equals(element.value, 'ABZFGHIJ', 'FormControlRange value after before-range shrink'); |
189 | | - assert_equals(range.startOffset, 5, 'FormControlRange start -2'); |
190 | | - assert_equals(range.endOffset, 8, 'FormControlRange end -2'); |
| 188 | + assert_equals(element.value, 'ABZFGHIJ', 'OpaqueRange value after before-range shrink'); |
| 189 | + assert_equals(range.startOffset, 5, 'OpaqueRange start -2'); |
| 190 | + assert_equals(range.endOffset, 8, 'OpaqueRange end -2'); |
191 | 191 | }, `Before-range shrink shifts left (${control})`); |
192 | 192 |
|
193 | 193 | test(() => { |
|
199 | 199 | assert_equals(domRange.startOffset, 2, 'DOM start unchanged'); |
200 | 200 | assert_equals(domRange.endOffset, 5, 'DOM end unchanged'); |
201 | 201 |
|
202 | | - // FormControlRange: same replacement via setRangeText. |
| 202 | + // OpaqueRange: same replacement via setRangeText. |
203 | 203 | const element = setup(control, 'ABCDEFGHIJ'); |
204 | 204 | const range = element.getValueRange(2, 5); |
205 | 205 | element.setRangeText('WXYZ', 7, 9); |
206 | | - assert_equals(element.value, 'ABCDEFGWXYZJ', 'FormControlRange value after after-range grow'); |
207 | | - assert_equals(range.startOffset, 2, 'FormControlRange start unchanged'); |
208 | | - assert_equals(range.endOffset, 5, 'FormControlRange end unchanged'); |
| 206 | + assert_equals(element.value, 'ABCDEFGWXYZJ', 'OpaqueRange value after after-range grow'); |
| 207 | + assert_equals(range.startOffset, 2, 'OpaqueRange start unchanged'); |
| 208 | + assert_equals(range.endOffset, 5, 'OpaqueRange end unchanged'); |
209 | 209 | }, `After-range grow leaves range unchanged (${control})`); |
210 | 210 |
|
211 | 211 | test(() => { |
|
217 | 217 | assert_equals(domRange.startOffset, 1, 'DOM collapsed to change start'); |
218 | 218 | assert_equals(domRange.endOffset, 1, 'DOM collapsed'); |
219 | 219 |
|
220 | | - // FormControlRange: same replacement via setRangeText. |
| 220 | + // OpaqueRange: same replacement via setRangeText. |
221 | 221 | const element = setup(control, 'ABCDEFG'); |
222 | 222 | const range = element.getValueRange(2, 5); |
223 | 223 | element.setRangeText('Q', 1, 6); |
224 | | - assert_equals(element.value, 'AQG', 'FormControlRange value after superset replacement'); |
225 | | - assert_equals(range.startOffset, 1, 'FormControlRange collapsed to change start'); |
226 | | - assert_equals(range.endOffset, 1, 'FormControlRange collapsed'); |
227 | | - assert_true(range.collapsed, 'FormControlRange collapsed flag true'); |
| 224 | + assert_equals(element.value, 'AQG', 'OpaqueRange value after superset replacement'); |
| 225 | + assert_equals(range.startOffset, 1, 'OpaqueRange collapsed to change start'); |
| 226 | + assert_equals(range.endOffset, 1, 'OpaqueRange collapsed'); |
| 227 | + assert_true(range.collapsed, 'OpaqueRange collapsed flag true'); |
228 | 228 | }, `Superset replacement collapses to change start (${control})`); |
229 | 229 |
|
230 | 230 | test(() => { |
|
236 | 236 | assert_equals(domRange.startOffset, 2, 'DOM start unchanged at boundary'); |
237 | 237 | assert_equals(domRange.endOffset, 6, 'DOM end +2'); |
238 | 238 |
|
239 | | - // FormControlRange: same insertion via setRangeText. |
| 239 | + // OpaqueRange: same insertion via setRangeText. |
240 | 240 | const element = setup(control, 'ABCDE'); |
241 | 241 | const range = element.getValueRange(2, 4); |
242 | 242 | element.setRangeText('QQ', 2, 2); |
243 | | - assert_equals(element.value, 'ABQQCDE', 'FormControlRange value after insert at start boundary'); |
244 | | - assert_equals(range.startOffset, 2, 'FormControlRange start unchanged at boundary'); |
245 | | - assert_equals(range.endOffset, 6, 'FormControlRange end +2'); |
| 243 | + assert_equals(element.value, 'ABQQCDE', 'OpaqueRange value after insert at start boundary'); |
| 244 | + assert_equals(range.startOffset, 2, 'OpaqueRange start unchanged at boundary'); |
| 245 | + assert_equals(range.endOffset, 6, 'OpaqueRange end +2'); |
246 | 246 | }, `Insert at range.start extends end (${control})`); |
247 | 247 |
|
248 | 248 | test(() => { |
|
254 | 254 | assert_equals(domRange.startOffset, 2, 'DOM start unchanged'); |
255 | 255 | assert_equals(domRange.endOffset, 4, 'DOM end unchanged at boundary'); |
256 | 256 |
|
257 | | - // FormControlRange: same insertion via setRangeText. |
| 257 | + // OpaqueRange: same insertion via setRangeText. |
258 | 258 | const element = setup(control, 'ABCDE'); |
259 | 259 | const range = element.getValueRange(2, 4); |
260 | 260 | element.setRangeText('QQ', 4, 4); |
261 | | - assert_equals(element.value, 'ABCDQQE', 'FormControlRange value after insert at end boundary'); |
262 | | - assert_equals(range.startOffset, 2, 'FormControlRange start unchanged'); |
263 | | - assert_equals(range.endOffset, 4, 'FormControlRange end unchanged at boundary'); |
| 261 | + assert_equals(element.value, 'ABCDQQE', 'OpaqueRange value after insert at end boundary'); |
| 262 | + assert_equals(range.startOffset, 2, 'OpaqueRange start unchanged'); |
| 263 | + assert_equals(range.endOffset, 4, 'OpaqueRange end unchanged at boundary'); |
264 | 264 | }, `Insert at range.end leaves range unchanged (${control})`); |
265 | 265 |
|
266 | 266 | test(() => { |
|
271 | 271 | assert_equals(domRange.startOffset, 1, 'DOM start unchanged inside growth'); |
272 | 272 | assert_equals(domRange.endOffset, 6, 'DOM end +2 code units'); |
273 | 273 |
|
274 | | - // FormControlRange: same replacement via setRangeText. |
| 274 | + // OpaqueRange: same replacement via setRangeText. |
275 | 275 | const element = setup(control, 'A😀BC'); |
276 | 276 | const range = element.getValueRange(1, 4); |
277 | 277 | element.setRangeText('🙂🙂', 1, 3); |
278 | | - assert_equals(range.startOffset, 1, 'FormControlRange start unchanged inside growth'); |
279 | | - assert_equals(range.endOffset, 6, 'FormControlRange end +2 code units'); |
| 278 | + assert_equals(range.startOffset, 1, 'OpaqueRange start unchanged inside growth'); |
| 279 | + assert_equals(range.endOffset, 6, 'OpaqueRange end +2 code units'); |
280 | 280 | }, `Surrogate pair expansion grows end (${control})`); |
281 | 281 |
|
282 | 282 | test(() => { |
|
289 | 289 | assert_equals(domRange.startOffset, 2, 'DOM start unchanged across interior edits'); |
290 | 290 | assert_equals(domRange.endOffset, 4, 'DOM end reflects cumulative delta'); |
291 | 291 |
|
292 | | - // FormControlRange: same edits via setRangeText. |
| 292 | + // OpaqueRange: same edits via setRangeText. |
293 | 293 | const element = setup(control, '012345'); |
294 | 294 | const range = element.getValueRange(2, 5); |
295 | 295 | element.setRangeText('XX', 3, 4); |
296 | 296 | element.setRangeText('', 3, 5); |
297 | | - assert_equals(element.value, '01245', 'FormControlRange final value after chained edits'); |
298 | | - assert_equals(range.startOffset, 2, 'FormControlRange start unchanged across interior edits'); |
299 | | - assert_equals(range.endOffset, 4, 'FormControlRange end reflects cumulative delta'); |
| 297 | + assert_equals(element.value, '01245', 'OpaqueRange final value after chained edits'); |
| 298 | + assert_equals(range.startOffset, 2, 'OpaqueRange start unchanged across interior edits'); |
| 299 | + assert_equals(range.endOffset, 4, 'OpaqueRange end reflects cumulative delta'); |
300 | 300 | }, `Chained interior edits cumulatively adjust range (${control})`); |
301 | 301 | }); |
302 | 302 | </script> |
0 commit comments