View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.html;
16  
17  import static java.nio.charset.StandardCharsets.UTF_8;
18  
19  import java.io.File;
20  import java.nio.file.Path;
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collections;
24  import java.util.List;
25  
26  import org.apache.commons.io.FileUtils;
27  import org.htmlunit.HttpMethod;
28  import org.htmlunit.MockWebConnection;
29  import org.htmlunit.Page;
30  import org.htmlunit.SimpleWebTestCase;
31  import org.junit.jupiter.api.Test;
32  import org.junit.jupiter.api.io.TempDir;
33  
34  /**
35   * Tests for {@link HtmlSelect}.
36   *
37   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
38   * @author Mike Williams
39   * @author Marc Guillemot
40   * @author Ahmed Ashour
41   * @author Ronald Brill
42   */
43  public class HtmlSelectTest extends SimpleWebTestCase {
44  
45      @TempDir
46      static Path TEMP_DIR_;
47  
48      /**
49       * Test the good path of submitting a select.
50       * @exception Exception If the test fails
51       */
52      @Test
53      public void select() throws Exception {
54          final String htmlContent = DOCTYPE_HTML
55              + "<html><head><title>foo</title></head><body>\n"
56              + "<form id='form1'><select name='select1'>\n"
57              + "<option value='option1'>Option1</option>\n"
58              + "<option value='option2' selected='selected'>Option2</option>\n"
59              + "<option value='option3'>Option3</option>\n"
60              + "</select>\n"
61              + "<input type='submit' name='button' value='foo'/>\n"
62              + "</form></body></html>";
63          final HtmlPage page = loadPage(htmlContent);
64          final MockWebConnection webConnection = getMockConnection(page);
65  
66          final HtmlForm form = page.getHtmlElementById("form1");
67  
68          final HtmlSelect select = form.getSelectsByName("select1").get(0);
69          final HtmlSubmitInput button = form.getInputByName("button");
70  
71          // Test that the select is being correctly identified as a submittable element
72          assertEquals(Arrays.asList(new Object[] {select, button}), form.getSubmittableElements(button));
73  
74          // Test that the correct value is being passed back up to the server
75          final HtmlPage secondPage = button.click();
76  
77          assertEquals("url", URL_FIRST + "?select1=option2&button=foo", secondPage.getUrl());
78          assertSame("method", HttpMethod.GET, webConnection.getLastMethod());
79          assertNotNull(secondPage);
80      }
81  
82      /**
83       * Tests submitting the select with no options selected.
84       * @exception Exception If the test fails
85       */
86      @Test
87      public void select_MultipleSelectNoneSelected() throws Exception {
88          final String htmlContent = DOCTYPE_HTML
89              + "<html><head><title>foo</title></head><body>\n"
90              + "<form id='form1'><select name='select1' multiple>\n"
91              + "<option value='option1'>Option1</option>\n"
92              + "<option value='option2'>Option2</option>\n"
93              + "<option value='option3'>Option3</option>\n"
94              + "</select>\n"
95              + "<input type='submit' name='button' value='foo'/>\n"
96              + "</form></body></html>";
97          final HtmlPage page = loadPage(htmlContent);
98          final MockWebConnection webConnection = getMockConnection(page);
99  
100         final HtmlForm form = page.getHtmlElementById("form1");
101 
102         final HtmlSelect select = form.getSelectsByName("select1").get(0);
103         assertNotNull(select);
104 
105         final HtmlSubmitInput button = form.getInputByName("button");
106 
107         // Test that the correct value is being passed back up to the server
108         final HtmlPage secondPage = button.click();
109 
110         assertEquals("url", URL_FIRST + "?button=foo", secondPage.getUrl());
111         assertSame("method", HttpMethod.GET, webConnection.getLastMethod());
112         assertNotNull(secondPage);
113     }
114 
115     /**
116      * Tests changing the selected option.
117      * @exception Exception If the test fails
118      */
119     @Test
120     public void select_ChangeSelectedOption_SingleSelect() throws Exception {
121         final String htmlContent = DOCTYPE_HTML
122             + "<html><head><title>foo</title></head><body>\n"
123             + "<form id='form1'><select name='select1'>\n"
124             + "<option value='option1' selected='selected'>Option1</option>\n"
125             + "<option value='option2'>Option2</option>\n"
126             + "<option value='option3'>Option3</option>\n"
127             + "</select>\n"
128             + "<input type='submit' name='button' value='foo'/>\n"
129             + "</form></body></html>";
130         final HtmlPage page = loadPage(htmlContent);
131         final MockWebConnection webConnection = getMockConnection(page);
132 
133         final HtmlForm form = page.getHtmlElementById("form1");
134 
135         final HtmlSelect select = form.getSelectsByName("select1").get(0);
136         final HtmlSubmitInput button = form.getInputByName("button");
137 
138         // Change the value
139         select.setSelectedAttribute("option3", true);
140 
141         // Test that the correct value is being passed back up to the server
142         final HtmlPage secondPage = button.click();
143 
144         assertEquals("url", URL_FIRST + "?select1=option3&button=foo", secondPage.getUrl());
145         assertSame("method", HttpMethod.GET, webConnection.getLastMethod());
146         assertNotNull(secondPage);
147     }
148 
149     /**
150      * Tests changing the selected option.
151      * @exception Exception If the test fails
152      */
153     @Test
154     public void select_ChangeSelectedOption_MultipleSelect() throws Exception {
155         final String htmlContent = DOCTYPE_HTML
156             + "<html><head><title>foo</title></head><body>\n"
157             + "<form id='form1'><select name='select1' multiple='multiple'>\n"
158             + "<option value='option1' selected='selected'>Option1</option>\n"
159             + "<option value='option2'>Option2</option>\n"
160             + "<option value='option3'>Option3</option>\n"
161             + "</select>\n"
162             + "<input type='submit' name='button' value='foo'/>\n"
163             + "</form></body></html>";
164         final HtmlPage page = loadPage(htmlContent);
165         final MockWebConnection webConnection = getMockConnection(page);
166 
167         final HtmlForm form = page.getHtmlElementById("form1");
168 
169         final HtmlSelect select = form.getSelectsByName("select1").get(0);
170         final HtmlSubmitInput button = form.getInputByName("button");
171 
172         // Change the value
173         select.setSelectedAttribute("option3", true);
174         select.setSelectedAttribute("option2", true);
175 
176         // Test that the correct value is being passed back up to the server
177         final HtmlPage secondPage = button.click();
178 
179         assertEquals("url", URL_FIRST + "?select1=option1&select1=option2&select1=option3&button=foo",
180                 secondPage.getUrl());
181         assertSame("method", HttpMethod.GET, webConnection.getLastMethod());
182         assertNotNull(secondPage);
183     }
184 
185     /**
186      * Tests multiple selected options on multiple select lists.
187      * @exception Exception If the test fails
188      */
189     @Test
190     public void select_MultipleSelectMultipleSelected() throws Exception {
191         final String htmlContent = DOCTYPE_HTML
192             + "<html><head><title>foo</title></head><body>\n"
193             + "<form id='form1'><select name='select1' multiple>\n"
194             + "<option value='option1' selected='selected'>Option1</option>\n"
195             + "<option value='option2'>Option2</option>\n"
196             + "<option value='option3' selected='selected'>Option3</option>\n"
197             + "</select>\n"
198             + "<input type='submit' name='button' value='foo'/>\n"
199             + "</form></body></html>";
200         final HtmlPage page = loadPage(htmlContent);
201 
202         final HtmlForm form = page.getHtmlElementById("form1");
203 
204         final HtmlSelect select = form.getSelectsByName("select1").get(0);
205         final List<HtmlOption> expected = new ArrayList<>();
206         expected.add(select.getOptionByValue("option1"));
207         expected.add(select.getOptionByValue("option3"));
208 
209         assertEquals(expected, select.getSelectedOptions());
210     }
211 
212     /**
213      * Test multiple selected options on single select lists. This is erroneous HTML, but
214      * browsers simply use the last option.
215      *
216      * @exception Exception If the test fails
217      */
218     @Test
219     public void select_SingleSelectMultipleSelected() throws Exception {
220         final String htmlContent = DOCTYPE_HTML
221             + "<html><head><title>foo</title></head><body>\n"
222             + "<form id='form1'><select name='select1'>\n"
223             + "<option value='option1' selected='selected'>Option1</option>\n"
224             + "<option value='option2'>Option2</option>\n"
225             + "<option value='option3' selected='selected'>Option3</option>\n"
226             + "</select>\n"
227             + "<input type='submit' name='button' value='foo'/>\n"
228             + "</form></body></html>";
229         final HtmlPage page = loadPage(htmlContent);
230 
231         final HtmlForm form = page.getHtmlElementById("form1");
232 
233         final HtmlSelect select = form.getSelectsByName("select1").get(0);
234         final List<HtmlOption> expected = new ArrayList<>();
235         expected.add(select.getOptionByValue("option3"));
236 
237         assertEquals(expected, select.getSelectedOptions());
238     }
239 
240     /**
241      * Test no selected options on single select lists. This is erroneous HTML, but
242      * browsers simply assume the first one to be selected
243      *
244      * @exception Exception If the test fails
245      */
246     @Test
247     public void select_SingleSelectNoneSelected() throws Exception {
248         final String htmlContent = DOCTYPE_HTML
249             + "<html><head><title>foo</title></head><body>\n"
250             + "<form id='form1'><select name='select1'>\n"
251             + "<option value='option1'>Option1</option>\n"
252             + "<option value='option2'>Option2</option>\n"
253             + "<option value='option3'>Option3</option>\n"
254             + "</select>\n"
255             + "<input type='submit' name='button' value='foo'/>\n"
256             + "</form></body></html>";
257         final HtmlPage page = loadPage(htmlContent);
258 
259         final HtmlForm form = page.getHtmlElementById("form1");
260 
261         final HtmlSelect select = form.getSelectsByName("select1").get(0);
262         final List<HtmlOption> expected = new ArrayList<>();
263         expected.add(select.getOptionByValue("option1"));
264 
265         assertEquals(expected, select.getSelectedOptions());
266     }
267 
268     /**
269      * Tests no selected options on single select lists with a size more than 1.
270      *
271      * @exception Exception If the test fails
272      */
273     @Test
274     public void select_SingleSelectNoneSelectedButSizeGreaterThanOne() throws Exception {
275         final String htmlContent = DOCTYPE_HTML
276             + "<html><head><title>foo</title></head><body>\n"
277             + "<form>\n"
278             + "<select name='select1' size='2' id='mySelect'>\n"
279             + "<option value='option1'>Option1</option>\n"
280             + "<option value='option2'>Option2</option>\n"
281             + "<option value='option3'>Option3</option>\n"
282             + "</select>\n"
283             + "</form></body></html>";
284 
285         final HtmlPage page = loadPage(htmlContent);
286 
287         final HtmlSelect select = page.getHtmlElementById("mySelect");
288 
289         assertEquals(Collections.EMPTY_LIST, select.getSelectedOptions());
290     }
291 
292     /**
293      * Tests changing the selected option.
294      * @exception Exception If the test fails
295      */
296     @Test
297     public void setSelected_IllegalValue() throws Exception {
298         final String htmlContent = DOCTYPE_HTML
299             + "<html><head><title>foo</title></head><body>\n"
300             + "<form id='form1'><select name='select1'>\n"
301             + "<option value='option1' selected='selected'>Option1</option>\n"
302             + "<option value='option2'>Option2</option>\n"
303             + "<option value='option3'>Option3</option>\n"
304             + "</select>\n"
305             + "<select name='select2'>\n"
306             + "</select>\n"
307             + "<input type='submit' name='button' value='foo'/>\n"
308             + "</form></body></html>";
309 
310         final HtmlPage page = loadPage(htmlContent);
311         final HtmlForm form = page.getHtmlElementById("form1");
312         final HtmlSelect select = form.getSelectByName("select1");
313 
314         select.setSelectedAttribute("missingOption", true);
315     }
316 
317     /**
318      * @throws Exception if the test fails
319      */
320     @Test
321     public void getOptions() throws Exception {
322         final String htmlContent = DOCTYPE_HTML
323             + "<html><head><title>foo</title></head><body>\n"
324             + "<form id='form1'><select name='select1'>\n"
325             + "<option value='option1' selected='selected'>Option1</option>\n"
326             + "<option value='option2'>Option2</option>\n"
327             + "<optgroup label='group1'>\n"
328             + "  <option value='option3'>Option3</option>\n"
329             + "</optgroup>\n"
330             + "</select>\n"
331             + "<input type='submit' name='button' value='foo'/>\n"
332             + "</form></body></html>";
333         final HtmlPage page = loadPage(htmlContent);
334 
335         final HtmlForm form = page.getHtmlElementById("form1");
336 
337         final HtmlSelect select = form.getSelectsByName("select1").get(0);
338 
339         final List<HtmlOption> expectedOptions = new ArrayList<>();
340         expectedOptions.add(select.getOptionByValue("option1"));
341         expectedOptions.add(select.getOptionByValue("option2"));
342         expectedOptions.add(select.getOptionByValue("option3"));
343 
344         assertEquals(expectedOptions, select.getOptions());
345     }
346 
347     /**
348      * @throws Exception if the test fails
349      */
350     @Test
351     public void select_OptionMultiple_NoValueOnAttribute() throws Exception {
352         final String htmlContent = DOCTYPE_HTML
353             + "<html><head><title>foo</title></head><body>\n"
354             + "<form id='form1'><select name='select1' id='select1' multiple>\n"
355             + "<option value='option1'>Option1</option>\n"
356             + "<option value='option2' >Option2</option>\n"
357             + "<option value='option3'>Option3</option>\n"
358             + "</select>\n"
359             + "<input type='submit' name='button' value='foo'/>\n"
360             + "</form></body></html>";
361         final HtmlPage page = loadPage(htmlContent);
362 
363         final HtmlSelect select = page.getHtmlElementById("select1");
364         assertTrue(select.isMultipleSelectEnabled());
365     }
366 
367     /**
368      * @throws Exception if the test fails
369      */
370     @Test
371     public void getOptionByValue() throws Exception {
372         final String htmlContent = DOCTYPE_HTML
373             + "<html><head><title>foo</title></head><body><form id='form1'>\n"
374             + "<select name='select1'>\n"
375             + "  <option value='option1'>s1o1</option>\n"
376             + "  <option value='option2'>s1o2</option>\n"
377             + "</select>\n"
378             + "<select name='select2'>\n"
379             + "  <option value='option1'>s2o1</option>\n"
380             + "  <option value='option2'>s2o2</option>\n"
381             + "  <option>s2o3</option>\n"
382             + "</select>\n"
383             + "<input type='submit' name='button' value='foo'/>\n"
384             + "</form></body></html>";
385         final HtmlPage page = loadPage(htmlContent);
386 
387         final HtmlForm form = page.getHtmlElementById("form1");
388 
389         final HtmlSelect select = form.getSelectsByName("select2").get(0);
390         assertEquals("s2o2", select.getOptionByValue("option2").asNormalizedText());
391 
392         assertEquals(select.getOption(2), select.getOptionByValue("s2o3"));
393     }
394 
395     /**
396      * @throws Exception if the test fails
397      */
398     @Test
399     public void select_SetSelected_OnChangeHandler() throws Exception {
400         final String htmlContent = DOCTYPE_HTML
401             + "<html><head><title>foo</title></head><body>\n"
402             + "<form id='form1'><select name='select1' onChange='alert(\"changing\")'>\n"
403             + "<option value='option1' selected='selected'>Option1</option>\n"
404             + "<option value='option2'>Option2</option>\n"
405             + "<option value='option3'>Option3</option>\n"
406             + "</select>\n"
407             + "<input type='submit' name='button' value='foo'/>\n"
408             + "</form></body></html>";
409         final List<String> collectedAlerts = new ArrayList<>();
410         final HtmlPage page = loadPage(htmlContent, collectedAlerts);
411 
412         final HtmlForm form = page.getHtmlElementById("form1");
413 
414         final HtmlSelect select = form.getSelectsByName("select1").get(0);
415 
416         // Change the value
417         select.setSelectedAttribute("option3", true);
418 
419         final String[] expectedAlerts = {"changing"};
420         assertEquals(expectedAlerts, collectedAlerts);
421     }
422 
423     /**
424      * @throws Exception if the test fails
425      */
426     @Test
427     public void setSelectionOnOptionWithNoName() throws Exception {
428         final String htmlContent = DOCTYPE_HTML
429             + "<html><body><form name='form' method='GET' action='action.html'>\n"
430             + "<select name='select' multiple size='5'>\n"
431             + "<option value='1'>111</option>\n"
432             + "<option id='option2'>222</option>\n"
433             + "</select>\n"
434             + "</form></body></html>";
435         final List<String> collectedAlerts = new ArrayList<>();
436         final HtmlPage page = loadPage(htmlContent, collectedAlerts);
437 
438         final HtmlOption option = page.getHtmlElementById("option2");
439         option.setSelected(true);
440     }
441 
442     private static void checkOptions(final HtmlSelect select) {
443         final List<HtmlOption> options = select.getOptions();
444         if (options.isEmpty()) {
445             assertNull(select.getFirstChild());
446             assertNull(select.getLastChild());
447         }
448         else {
449             assertEquals(options.get(0), select.getFirstChild());
450             assertEquals(options.get(options.size() - 1), select.getLastChild());
451         }
452     }
453 
454     /**
455      * @throws Exception if the test fails
456      */
457     @Test
458     public void removeOptionsFromSelect() throws Exception {
459         final String htmlContent = DOCTYPE_HTML
460             + "<html><body><form name='form' method='GET' action='action.html'>\n"
461             + "<select name='select' id='theSelect'>"
462             + "<option value='a'>111</option>"
463             + "<option value='b'>222</option>"
464             + "<option value='c'>333</option>"
465             + "<option value='d'>444</option>"
466             + "</select>\n"
467             + "</form></body></html>";
468         final HtmlPage page = loadPage(htmlContent);
469 
470         final HtmlSelect theSelect = page.getHtmlElementById("theSelect");
471         assertNotNull(theSelect);
472 
473         assertEquals(4, theSelect.getOptions().size());
474         assertEquals("a", theSelect.getOption(0).getValueAttribute());
475         assertEquals("b", theSelect.getOption(1).getValueAttribute());
476         assertEquals("c", theSelect.getOption(2).getValueAttribute());
477         assertEquals("d", theSelect.getOption(3).getValueAttribute());
478 
479         // remove from the middle
480         theSelect.getOption(1).remove();
481         checkOptions(theSelect);
482         assertEquals(3, theSelect.getOptions().size());
483         assertEquals("a", theSelect.getOption(0).getValueAttribute());
484         assertEquals("c", theSelect.getOption(1).getValueAttribute());
485         assertEquals("d", theSelect.getOption(2).getValueAttribute());
486 
487         // remove from the end
488         theSelect.getOption(2).remove();
489         checkOptions(theSelect);
490         assertEquals(2, theSelect.getOptions().size());
491         assertEquals("a", theSelect.getOption(0).getValueAttribute());
492         assertEquals("c", theSelect.getOption(1).getValueAttribute());
493 
494         // remove from the front
495         theSelect.getOption(0).remove();
496         checkOptions(theSelect);
497         assertEquals(1, theSelect.getOptions().size());
498         assertEquals("c", theSelect.getOption(0).getValueAttribute());
499 
500         // remove from the last one
501         theSelect.getOption(0).remove();
502         checkOptions(theSelect);
503         assertEquals(0, theSelect.getOptions().size());
504     }
505 
506     /**
507      * @throws Exception if the test fails
508      */
509     @Test
510     public void editOptions() throws Exception {
511         final String htmlContent = DOCTYPE_HTML
512             + "<html><body><form name='form' method='GET' action='action.html'>\n"
513             + "<select name='select' id='theSelect'>\n"
514             + "<option value='a'>111</option>\n"
515             + "<option value='b'>222</option>\n"
516             + "<option value='c'>333</option>\n"
517             + "</select>\n"
518             + "</form></body></html>";
519         final HtmlPage page = loadPage(htmlContent);
520 
521         final HtmlSelect theSelect = page.getHtmlElementById("theSelect");
522 
523         assertNotNull(theSelect);
524         assertEquals(3, theSelect.getOptions().size());
525 
526         appendOption(theSelect, "d");
527         assertEquals(4, theSelect.getOptions().size());
528         assertEquals("d", theSelect.getOption(3).getValueAttribute());
529 
530         theSelect.setOptionSize(1);
531         assertEquals(1, theSelect.getOptions().size());
532         assertEquals("a", theSelect.getOption(0).getValueAttribute());
533 
534         appendOption(theSelect, "x");
535         assertEquals(2, theSelect.getOptions().size());
536         assertEquals("x", theSelect.getOption(1).getValueAttribute());
537     }
538 
539     void appendOption(final HtmlSelect select, final String value) {
540         final HtmlOption option = (HtmlOption) select.getPage().getWebClient().getPageCreator().getHtmlParser()
541                     .getFactory(HtmlOption.TAG_NAME).createElement(select.getPage(), HtmlOption.TAG_NAME, null);
542         option.setValueAttribute(value);
543         option.setLabelAttribute(value);
544         select.appendOption(option);
545     }
546 
547     /**
548      * Test that asNormalizedText() returns a blank string if nothing is selected.
549      *
550      * @exception Exception If the test fails
551      */
552     @Test
553     public void asNormalizedTextWhenNothingSelected() throws Exception {
554         final String htmlContent = DOCTYPE_HTML
555             + "<html><head><title>foo</title></head><body>\n"
556             + "<form>\n"
557             + "<select name='select1' size='1' id='mySelect'>\n"
558             + "</select>\n"
559             + "</form></body></html>";
560 
561         final HtmlPage page = loadPage(htmlContent);
562 
563         final HtmlSelect select = page.getHtmlElementById("mySelect");
564 
565         assertEquals("", select.asNormalizedText());
566     }
567 
568     /**
569      * Verifies that asNormalizedText() returns all options when multiple options are selectable, instead of just
570      * the selected ones.
571      * @throws Exception if an error occurs
572      */
573     @Test
574     public void asNormalizedTextWithMultipleSelect() throws Exception {
575         final String html = DOCTYPE_HTML
576             + "<html><body><form>\n"
577             + "<select name='a' multiple>\n"
578             + "<option value='1'selected>foo</option>\n"
579             + "<option value='2'>bar</option>\n"
580             + "<option value='3' selected>baz</option>\n"
581             + "</select>\n"
582             + "</form></body></html>";
583         final HtmlPage page = loadPage(html);
584         final HtmlSelect select = (HtmlSelect) page.getDocumentElement().getElementsByTagName("select").get(0);
585         assertEquals("foo\nbaz", select.asNormalizedText());
586     }
587 
588     /**
589      * Test that setSelectedAttribute returns the right page.
590      *
591      * @exception Exception If the test fails
592      */
593     @Test
594     public void setSelectedAttributeReturnedPage() throws Exception {
595         final String content = DOCTYPE_HTML
596             + "<html><head><title>foo</title>\n"
597             + "<script>\n"
598             + "function test() {\n"
599             + "  document.getElementById('iframe').src = 'about:blank';\n"
600             + "}\n"
601             + "</script>\n"
602             + "</head><body>\n"
603             + "<form>\n"
604             + "<select name='select1' size='1' id='mySelect' onchange='test()'>\n"
605             + "<option value='option1'>option 1</option>\n"
606             + "<option value='option2'>option 2</option>\n"
607             + "</select>\n"
608             + "</form>\n"
609             + "<iframe id='iframe' src='about:blank'></iframe>\n"
610             + "</body></html>";
611 
612         final HtmlPage page = loadPage(content);
613 
614         final HtmlSelect select = page.getHtmlElementById("mySelect");
615         final HtmlOption option = select.getOptionByValue("option2");
616         final Page page2 = select.setSelectedAttribute(option, true);
617         assertEquals(page, page2);
618     }
619 
620     /**
621      * @throws Exception if the test fails
622      */
623     @Test
624     public void onChangeResultPage() throws Exception {
625         final String htmlContent = DOCTYPE_HTML
626             + "<html><head><title>foo</title></head><body>\n"
627             + "<form id='form1'>\n"
628             + "<select name='select1' id='select1' onchange='location=\"about:blank\"'>\n"
629             + "  <option id='option1'>Option1</option>\n"
630             + "  <option id='option2' selected>Number Two</option>\n"
631             + "</select>\n"
632             + "</form></body></html>";
633 
634         final HtmlPage page = loadPage(htmlContent);
635 
636         final HtmlOption option1 = page.getHtmlElementById("option1");
637         final HtmlPage page2 = option1.click();
638         assertEquals("about:blank", page2.getUrl());
639     }
640 
641     /**
642      * @throws Exception if the test fails
643      */
644     @Test
645     public void onChange_resultPage_newCurrentWindow() throws Exception {
646         final String htmlContent = DOCTYPE_HTML
647             + "<html><head><title>foo</title></head><body>\n"
648             + "<form id='form1'>\n"
649             + "<select name='select1' id='select1' onchange='window.open(\"about:blank\", \"_blank\")'>\n"
650             + "  <option id='option1'>Option1</option>\n"
651             + "  <option id='option2' selected>Number Two</option>\n"
652             + "</select>\n"
653             + "</form></body></html>";
654 
655         final HtmlPage page = loadPage(htmlContent);
656 
657         final HtmlSelect select = page.getHtmlElementById("select1");
658         final HtmlOption option1 = page.getHtmlElementById("option1");
659         final HtmlPage page2 = select.setSelectedAttribute(option1, true);
660         assertEquals("about:blank", page2.getUrl());
661     }
662 
663     /**
664      * @throws Exception if the test fails
665      */
666     @Test
667     public void asXml_size() throws Exception {
668         final String content = DOCTYPE_HTML
669             + "<html><head><title>foo</title></head>\n"
670             + "<body>\n"
671             + "<select/>\n"
672             + "</body></html>";
673 
674         final HtmlPage page = loadPage(content);
675         assertEquals(-1, page.asXml().indexOf("size"));
676     }
677 
678     /**
679      * @throws Exception if the test fails
680      */
681     @Test
682     public void select_focus() throws Exception {
683         final String htmlContent = DOCTYPE_HTML
684             + "<html><head><title>foo</title></head><body>\n"
685             + "<form id='form1'>\n"
686             + "<select name='select1' id='select1' multiple onfocus='alert(\"focus\")'>\n"
687             + "<option value='option1'>Option1</option>\n"
688             + "<option value='option2'>Option2</option>\n"
689             + "<option value='option3' selected>Option3</option>\n"
690             + "</select>\n"
691             + "<input type='submit' name='button' value='foo'/>\n"
692             + "</form></body></html>";
693 
694         final List<String> collectedAlerts = new ArrayList<>();
695         final HtmlPage page = loadPage(htmlContent, collectedAlerts);
696         assertEquals(Collections.emptyList(), collectedAlerts);
697 
698         final HtmlSelect select = page.getHtmlElementById("select1");
699         assertNotSame(select, page.getFocusedElement());
700         select.getOption(0).setSelected(true);
701         assertSame(select, page.getFocusedElement());
702 
703         final String[] expectedAlerts = {"focus"};
704         assertEquals(expectedAlerts, collectedAlerts);
705     }
706 
707     /**
708      * @throws Exception if the test fails
709      */
710     @Test
711     public void getOptionByText() throws Exception {
712         final String html = DOCTYPE_HTML
713             + "<html><head><title>foo</title></head><body><form id='form1'>\n"
714             + "<select name='select1'>\n"
715             + "  <option value='option1'>s1o1</option>\n"
716             + "  <option value='option2'>s1o2</option>\n"
717             + "</select>\n"
718             + "<select name='select2'>\n"
719             + "  <option value='option1'>s2o1</option>\n"
720             + "  <option value='option2'>s2o2</option>\n"
721             + "  <option>s2o3</option>\n"
722             + "</select>\n"
723             + "<input type='submit' name='button' value='foo'/>\n"
724             + "</form></body></html>";
725         final HtmlPage page = loadPage(html);
726 
727         final HtmlForm form = page.getHtmlElementById("form1");
728 
729         final HtmlSelect select = form.getSelectsByName("select2").get(0);
730         assertEquals("s2o2", select.getOptionByText("s2o2").asNormalizedText());
731 
732         assertEquals(select.getOption(2), select.getOptionByText("s2o3"));
733     }
734 
735     /**
736      * @throws Exception if the test fails
737      */
738     @Test
739     public void savePageSavesSelectedOption() throws Exception {
740         final String content = DOCTYPE_HTML
741             + "<html><body>\n"
742             + "<form action=''>\n"
743             + "  <select id='main'>\n"
744             + "    <option value='1'>option 1</option>\n"
745             + "    <option value='2'>option 2</option>\n"
746             + "    <option value='3' selected>option 3</option>\n"
747             + "  </select>\n"
748             + "</form>\n"
749             + "<script>\n"
750             + "var oSelect = document.getElementById('main');\n"
751             + "oSelect.options[1].selected = true;\n"
752             + "alert(oSelect.options[1].getAttribute('selected'));\n"
753             + "</script>\n"
754             + "</body></html>";
755 
756         final HtmlPage page = loadPage(content);
757         final HtmlSelect select = (HtmlSelect) page.getElementById("main");
758         assertEquals("option 2", select.getSelectedOptions().get(0).getText());
759 
760         // save the file and reload it
761         final File tmpFolder = new File(TEMP_DIR_.toFile(), "hu");
762         tmpFolder.mkdir();
763         final File file = new File(tmpFolder, "test.html");
764         FileUtils.deleteQuietly(file);
765 
766         page.save(file);
767         final String html2 = FileUtils.readFileToString(file, UTF_8);
768         final HtmlPage page2 = loadPage(html2);
769         final HtmlSelect select2 = (HtmlSelect) page2.getElementById("main");
770         assertEquals("option 2", select2.getSelectedOptions().get(0).getText());
771     }
772 }