• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / httpunit / 656

06 Dec 2025 09:11PM UTC coverage: 80.452% (+0.02%) from 80.435%
656

push

github

hazendaz
[maven-release-plugin] prepare for next development iteration

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8245 of 10137 relevant lines covered (81.34%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.84
/src/main/java/com/meterware/httpunit/WebForm.java
1
/*
2
 * MIT License
3
 *
4
 * Copyright 2011-2025 Russell Gold
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
7
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
9
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions
12
 * of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
15
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
17
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18
 * DEALINGS IN THE SOFTWARE.
19
 */
20
package com.meterware.httpunit;
21

22
import com.meterware.httpunit.protocol.ParameterProcessor;
23
import com.meterware.httpunit.protocol.UploadFileSpec;
24
import com.meterware.httpunit.scripting.FormScriptable;
25
import com.meterware.httpunit.scripting.IdentifiedDelegate;
26
import com.meterware.httpunit.scripting.NamedDelegate;
27
import com.meterware.httpunit.scripting.ScriptableDelegate;
28

29
import java.io.File;
30
import java.io.IOException;
31
import java.net.URL;
32
import java.net.UnknownServiceException;
33
import java.util.ArrayList;
34
import java.util.HashMap;
35
import java.util.List;
36
import java.util.Map;
37

38
import org.w3c.dom.Node;
39
import org.w3c.dom.html.HTMLCollection;
40
import org.w3c.dom.html.HTMLFormElement;
41
import org.xml.sax.SAXException;
42

43
/**
44
 * This class represents a form in an HTML page. Users of this class may examine the parameters defined for the form,
45
 * the structure of the form (as a DOM), or the text of the form. They may also create a {@link WebRequest} to simulate
46
 * the submission of the form.
47
 **/
48
public class WebForm extends WebRequestSource {
49

50
    /** The Constant NO_VALUES. */
51
    private static final String[] NO_VALUES = {};
1✔
52

53
    /** The buttons. */
54
    private Button[] _buttons;
55

56
    /** The submit buttons in this form. **/
57
    private SubmitButton[] _submitButtons;
58

59
    /** The character set in which the form will be submitted. **/
60
    private String _characterSet;
61

62
    /** The button list. */
63
    private List<SubmitButton> _buttonVector;
64

65
    /** The preset parameters. */
66
    private FormControl[] _presetParameters;
67

68
    /** The presets. */
69
    private ArrayList _presets;
70

71
    /** The registry. */
72
    private ElementRegistry _registry;
73

74
    /** Predicate to match a link's name. **/
75
    public static final HTMLElementPredicate MATCH_NAME;
76

77
    /** The dom element. */
78
    private HTMLFormElement _domElement;
79

80
    /**
81
     * Submits this form using the web client from which it was originally obtained.
82
     *
83
     * @return the web response
84
     *
85
     * @throws IOException
86
     *             Signals that an I/O exception has occurred.
87
     * @throws SAXException
88
     *             the SAX exception
89
     */
90
    public WebResponse submit() throws IOException, SAXException {
91
        return submit(getDefaultButton());
1✔
92
    }
93

94
    /**
95
     * Submits this form using the web client from which it was originally obtained. Will usually return the result of
96
     * that submission; however, if the submit button's 'onclick' or the form's 'onsubmit' event is triggered and
97
     * inhibits the submission, will return the updated contents of the frame containing this form.
98
     *
99
     * @param button
100
     *            the button
101
     *
102
     * @return the web response
103
     *
104
     * @throws IOException
105
     *             Signals that an I/O exception has occurred.
106
     * @throws SAXException
107
     *             the SAX exception
108
     */
109
    public WebResponse submit(SubmitButton button) throws IOException, SAXException {
110
        return submit(button, 0, 0);
1✔
111
    }
112

113
    /**
114
     * Submits this form using the web client from which it was originally obtained. Will usually return the result of
115
     * that submission; however, if the submit button's 'onclick' or the form's 'onsubmit' event is triggered and
116
     * inhibits the submission, will return the updated contents of the frame containing this form.
117
     *
118
     * @param button
119
     *            the button
120
     * @param x
121
     *            the x
122
     * @param y
123
     *            the y
124
     *
125
     * @return the web response
126
     *
127
     * @throws IOException
128
     *             Signals that an I/O exception has occurred.
129
     * @throws SAXException
130
     *             the SAX exception
131
     */
132
    public WebResponse submit(SubmitButton button, int x, int y) throws IOException, SAXException {
133
        if (button == null) {
1✔
134
            throw new IllegalSubmitButtonException("?", "?");
1✔
135
        }
136
        button.doOnClickSequence(x, y);
1✔
137
        return getCurrentFrameContents();
1✔
138
    }
139

140
    /**
141
     * Submits this form using the web client from which it was originally obtained, ignoring any buttons defined for
142
     * the form.
143
     *
144
     * @return the web response
145
     *
146
     * @throws SAXException
147
     *             the SAX exception
148
     * @throws IOException
149
     *             Signals that an I/O exception has occurred.
150
     */
151
    public WebResponse submitNoButton() throws SAXException, IOException {
152
        return submit(SubmitButton.createFakeSubmitButton(this /* fake */));
1✔
153
    }
154

155
    @Override
156
    protected WebResponse submitRequest(String event, WebRequest request) throws IOException, SAXException {
157
        try {
158
            return super.submitRequest(event, request);
1✔
159
        } catch (UnknownServiceException e) {
1✔
160
            throw new UnsupportedActionException(
1✔
161
                    "HttpUnit does not support " + request.getURL().getProtocol() + " URLs in form submissions");
1✔
162
        }
163
    }
164

165
    /**
166
     * Submits the form without also invoking the button's "onclick" event.
167
     *
168
     * @param button
169
     *            the button
170
     *
171
     * @return the web response
172
     *
173
     * @throws IOException
174
     *             Signals that an I/O exception has occurred.
175
     * @throws SAXException
176
     *             the SAX exception
177
     */
178
    WebResponse doFormSubmit(SubmitButton button) throws IOException, SAXException {
179
        return submitRequest(getAttribute("onsubmit"), getRequest(button));
×
180
    }
181

182
    /**
183
     * Do form submit.
184
     *
185
     * @param button
186
     *            the button
187
     * @param x
188
     *            the x
189
     * @param y
190
     *            the y
191
     *
192
     * @return the web response
193
     *
194
     * @throws IOException
195
     *             Signals that an I/O exception has occurred.
196
     * @throws SAXException
197
     *             the SAX exception
198
     */
199
    WebResponse doFormSubmit(SubmitButton button, int x, int y) throws IOException, SAXException {
200
        return submitRequest(getAttribute("onsubmit"), getRequest(button, x, y));
1✔
201
    }
202

203
    /**
204
     * Returns the method defined for this form.
205
     *
206
     * @return the method
207
     */
208
    public String getMethod() {
209
        return getAttribute("method", "GET");
1✔
210
    }
211

212
    /**
213
     * Returns the action defined for this form.
214
     *
215
     * @return the action
216
     */
217
    public String getAction() {
218
        return getDestination();
1✔
219
    }
220

221
    /**
222
     * Returns true if a parameter with given name exists in this form.
223
     *
224
     * @param soughtName
225
     *            the sought name
226
     *
227
     * @return true, if successful
228
     */
229
    public boolean hasParameterNamed(String soughtName) {
230
        return getFormParameters().containsKey(soughtName);
1✔
231
    }
232

233
    /**
234
     * Returns true if a parameter starting with a given name exists,.
235
     *
236
     * @param prefix
237
     *            the prefix
238
     *
239
     * @return true, if successful
240
     */
241
    public boolean hasParameterStartingWithPrefix(String prefix) {
242
        String[] names = getParameterNames();
1✔
243
        for (String name : names) {
1!
244
            if (name.startsWith(prefix)) {
1✔
245
                return true;
1✔
246
            }
247
        }
248
        return false;
×
249
    }
250

251
    /**
252
     * Returns an array containing all of the buttons defined for this form.
253
     *
254
     * @return the buttons
255
     */
256
    public Button[] getButtons() {
257
        if (_buttons == null) {
1✔
258
            FormControl[] controls = getFormControls();
1✔
259
            List<FormControl> buttonList = new ArrayList<>();
1✔
260
            for (FormControl control : controls) {
1✔
261
                if (control instanceof Button) {
1✔
262
                    buttonList.add(control);
1✔
263
                }
264
            }
265
            _buttons = (Button[]) buttonList.toArray(new Button[buttonList.size()]);
1✔
266
        }
267
        return _buttons;
1✔
268
    }
269

270
    /**
271
     * Gets the button.
272
     *
273
     * @param predicate
274
     *            the predicate
275
     * @param criteria
276
     *            the criteria
277
     *
278
     * @return the button
279
     */
280
    public Button getButton(HTMLElementPredicate predicate, Object criteria) {
281
        Button[] buttons = getButtons();
1✔
282
        for (Button button : buttons) {
1!
283
            if (predicate.matchesCriteria(button, criteria)) {
1✔
284
                return button;
1✔
285
            }
286
        }
287
        return null;
×
288
    }
289

290
    /**
291
     * Convenience method which returns the button with the specified ID.
292
     *
293
     * @param buttonID
294
     *            the button ID
295
     *
296
     * @return the button with ID
297
     */
298
    public Button getButtonWithID(String buttonID) {
299
        return getButton(Button.WITH_ID, buttonID);
1✔
300
    }
301

302
    /**
303
     * Returns an array containing the submit buttons defined for this form.
304
     *
305
     * @return the submit buttons
306
     */
307
    public SubmitButton[] getSubmitButtons() {
308
        if (_submitButtons == null) {
1✔
309
            List<SubmitButton> buttons = getSubmitButtonVector();
1✔
310
            _submitButtons = buttons.toArray(new SubmitButton[buttons.size()]);
1✔
311
        }
312
        return _submitButtons;
1✔
313
    }
314

315
    /**
316
     * Returns the submit button defined in this form with the specified name. If more than one such button exists, will
317
     * return the first found. If no such button is found, will return null.
318
     *
319
     * @param name
320
     *            the name
321
     *
322
     * @return the submit button
323
     */
324
    public SubmitButton getSubmitButton(String name) {
325
        SubmitButton[] buttons = getSubmitButtons();
1✔
326
        for (SubmitButton button : buttons) {
1✔
327
            if (button.getName().equals(name)) {
1✔
328
                return button;
1✔
329
            }
330
        }
331
        return null;
1✔
332
    }
333

334
    /**
335
     * Returns the submit button defined in this form with the specified name and value. If more than one such button
336
     * exists, will return the first found. If no such button is found, will return null.
337
     *
338
     * @param name
339
     *            the name
340
     * @param value
341
     *            the value
342
     *
343
     * @return the submit button
344
     */
345
    public SubmitButton getSubmitButton(String name, String value) {
346
        SubmitButton[] buttons = getSubmitButtons();
1✔
347
        for (SubmitButton button : buttons) {
1!
348
            if (button.getName().equals(name) && button.getValue().equals(value)) {
1!
349
                return button;
1✔
350
            }
351
        }
352
        return null;
×
353
    }
354

355
    /**
356
     * Returns the submit button defined in this form with the specified ID. If more than one such button exists, will
357
     * return the first found. If no such button is found, will return null.
358
     *
359
     * @param ID
360
     *            the id
361
     *
362
     * @return the submit button with ID
363
     */
364
    public SubmitButton getSubmitButtonWithID(String ID) {
365
        SubmitButton[] buttons = getSubmitButtons();
1✔
366
        for (SubmitButton button : buttons) {
1!
367
            if (button.getID().equals(ID)) {
1!
368
                return button;
1✔
369
            }
370
        }
371
        return null;
×
372
    }
373

374
    /**
375
     * Creates and returns a web request which will simulate the submission of this form with a button with the
376
     * specified name and value.
377
     *
378
     * @param submitButtonName
379
     *            the submit button name
380
     * @param submitButtonValue
381
     *            the submit button value
382
     *
383
     * @return the request
384
     */
385
    public WebRequest getRequest(String submitButtonName, String submitButtonValue) {
386
        SubmitButton sb = getSubmitButton(submitButtonName, submitButtonValue);
1✔
387
        if (sb == null) {
1!
388
            throw new IllegalSubmitButtonException(submitButtonName, submitButtonValue);
×
389
        }
390
        return getRequest(sb);
1✔
391
    }
392

393
    /**
394
     * Creates and returns a web request which will simulate the submission of this form with a button with the
395
     * specified name.
396
     *
397
     * @param submitButtonName
398
     *            the submit button name
399
     *
400
     * @return the request
401
     */
402
    public WebRequest getRequest(String submitButtonName) {
403
        SubmitButton sb = getSubmitButton(submitButtonName);
1✔
404
        if (sb == null) {
1!
405
            throw new IllegalSubmitButtonException(submitButtonName, "");
×
406
        }
407
        return getRequest(sb);
1✔
408
    }
409

410
    /**
411
     * Creates and returns a web request which will simulate the submission of this form by pressing the specified
412
     * button. If the button is null, simulates the pressing of the default button.
413
     *
414
     * @param button
415
     *            the button
416
     *
417
     * @return the request
418
     */
419
    public WebRequest getRequest(SubmitButton button) {
420
        return getRequest(button, 0, 0);
1✔
421
    }
422

423
    /**
424
     * Creates and returns a web request which will simulate the submission of this form by pressing the specified
425
     * button. If the button is null, simulates the pressing of the default button.
426
     *
427
     * @param button
428
     *            - the submitbutton to be pressed - may be null
429
     * @param x
430
     *            - the x position
431
     * @param y
432
     *            - the y position
433
     *
434
     * @return the request
435
     */
436
    public WebRequest getRequest(SubmitButton button, int x, int y) {
437
        if (button == null) {
1✔
438
            button = getDefaultButton();
1✔
439
        }
440

441
        if (HttpUnitOptions.getParameterValuesValidated()) {
1✔
442
            if (button == null) {
1✔
443
                throw new IllegalUnnamedSubmitButtonException();
1✔
444
            }
445
            if (button.isFake()) {
1✔
446
                // bypass checks
447
            } else if (!getSubmitButtonVector().contains(button)) {
1✔
448
                throw new IllegalSubmitButtonException(button);
1✔
449
            } else if (!button.wasEnabled()) {
1✔
450
                // this is too late for the check of isDisabled()
451
                // onclick has already been done ...
452
                // [ 1289151 ] Order of events in button.click() is wrong
453
                button.throwDisabledException();
×
454
            }
455
        }
456

457
        SubmitButton[] buttons = getSubmitButtons();
1✔
458
        for (SubmitButton button2 : buttons) {
1✔
459
            button2.setPressed(false);
1✔
460
        }
461
        button.setPressed(true);
1✔
462

463
        if (getMethod().equalsIgnoreCase("post")) {
1✔
464
            return new PostMethodWebRequest(this, button, x, y);
1✔
465
        }
466
        return new GetMethodWebRequest(this, WebRequest.newParameterHolder(this), button, x, y);
1✔
467
    }
468

469
    /**
470
     * Creates and returns a web request which includes the specified button. If no button is specified, will include
471
     * the default button, if any. No parameter validation will be done on the returned request and no scripts will be
472
     * run when it is submitted.
473
     *
474
     * @param button
475
     *            the button
476
     *
477
     * @return the web request
478
     */
479
    public WebRequest newUnvalidatedRequest(SubmitButton button) {
480
        return newUnvalidatedRequest(button, 0, 0);
1✔
481
    }
482

483
    /**
484
     * Creates and returns a web request which includes the specified button and position. If no button is specified,
485
     * will include the default button, if any. No parameter validation will be done on the returned request and no
486
     * scripts will be run when it is submitted.
487
     *
488
     * @param button
489
     *            the button
490
     * @param x
491
     *            the x
492
     * @param y
493
     *            the y
494
     *
495
     * @return the web request
496
     */
497
    public WebRequest newUnvalidatedRequest(SubmitButton button, int x, int y) {
498
        if (button == null) {
1✔
499
            button = getDefaultButton();
1✔
500
        }
501

502
        SubmitButton[] buttons = getSubmitButtons();
1✔
503
        for (SubmitButton button2 : buttons) {
1✔
504
            button2.setPressed(false);
1✔
505
        }
506
        button.setPressed(true);
1✔
507

508
        if (getMethod().equalsIgnoreCase("post")) {
1✔
509
            return new PostMethodWebRequest(this, new UncheckedParameterHolder(this), button, x, y);
1✔
510
        }
511
        return new GetMethodWebRequest(this, new UncheckedParameterHolder(this), button, x, y);
1✔
512
    }
513

514
    /**
515
     * Gets the scripted submit request.
516
     *
517
     * @return the scripted submit request
518
     */
519
    private WebRequest getScriptedSubmitRequest() {
520
        SubmitButton[] buttons = getSubmitButtons();
1✔
521
        for (SubmitButton button : buttons) {
1✔
522
            button.setPressed(false);
1✔
523
        }
524

525
        if (getMethod().equalsIgnoreCase("post")) {
1✔
526
            return new PostMethodWebRequest(this);
1✔
527
        }
528
        return new GetMethodWebRequest(this);
1✔
529

530
    }
531

532
    /**
533
     * Returns the default value of the named parameter. If the parameter does not exist returns null.
534
     *
535
     * @param name
536
     *            the name
537
     *
538
     * @return the parameter value
539
     */
540
    public String getParameterValue(String name) {
541
        String[] values = getParameterValues(name);
1✔
542
        return values.length == 0 ? null : values[0];
1✔
543
    }
544

545
    /**
546
     * Returns the displayed options defined for the specified parameter name.
547
     *
548
     * @param name
549
     *            the name
550
     *
551
     * @return the options
552
     */
553
    public String[] getOptions(String name) {
554
        return getParameter(name).getOptions();
1✔
555
    }
556

557
    /**
558
     * Returns the option values defined for the specified parameter name.
559
     *
560
     * @param name
561
     *            the name
562
     *
563
     * @return the option values
564
     */
565
    public String[] getOptionValues(String name) {
566
        return getParameter(name).getOptionValues();
1✔
567
    }
568

569
    /**
570
     * Returns true if the named parameter accepts multiple values.
571
     *
572
     * @param name
573
     *            the name
574
     *
575
     * @return true, if is multi valued parameter
576
     */
577
    public boolean isMultiValuedParameter(String name) {
578
        return getParameter(name).isMultiValuedParameter();
×
579
    }
580

581
    /**
582
     * Returns the number of text parameters in this form with the specified name.
583
     *
584
     * @param name
585
     *            the name
586
     *
587
     * @return the num text parameters
588
     */
589
    public int getNumTextParameters(String name) {
590
        return getParameter(name).getNumTextParameters();
1✔
591
    }
592

593
    /**
594
     * Returns true if the named parameter accepts free-form text.
595
     *
596
     * @param name
597
     *            the name
598
     *
599
     * @return true, if is text parameter
600
     */
601
    public boolean isTextParameter(String name) {
602
        return getParameter(name).isTextParameter();
×
603
    }
604

605
    /**
606
     * Returns true if this form is to be submitted using mime encoding (the default is URL encoding).
607
     **/
608
    @Override
609
    public boolean isSubmitAsMime() {
610
        return "multipart/form-data".equalsIgnoreCase(getAttribute("enctype"));
1✔
611
    }
612

613
    /**
614
     * Gets the scriptable object.
615
     *
616
     * @return the scriptable object
617
     */
618
    public FormScriptable getScriptableObject() {
619
        return (FormScriptable) getScriptingHandler();
1✔
620
    }
621

622
    /**
623
     * Resets all parameters to their initial values.
624
     */
625
    public void reset() {
626
        if (handleEvent("onreset")) {
1!
627
            resetControls();
1✔
628
        }
629
    }
1✔
630

631
    /**
632
     * Reset controls.
633
     */
634
    private void resetControls() {
635
        FormControl[] controls = getFormControls();
1✔
636
        for (FormControl control : controls) {
1✔
637
            control.reset();
1✔
638
        }
639
    }
1✔
640

641
    @Override
642
    public ScriptableDelegate newScriptable() {
643
        return new Scriptable();
1✔
644
    }
645

646
    // ---------------------------------- WebRequestSource methods
647
    // --------------------------------
648

649
    /**
650
     * Returns the character set encoding for this form.
651
     **/
652
    @Override
653
    public String getCharacterSet() {
654
        return _characterSet;
1✔
655
    }
656

657
    /**
658
     * Returns true if the named parameter accepts files for upload.
659
     **/
660
    @Override
661
    public boolean isFileParameter(String name) {
662
        return getParameter(name).isFileParameter();
1✔
663
    }
664

665
    /**
666
     * Returns an array containing the names of the parameters defined for this form.
667
     **/
668
    @Override
669
    public String[] getParameterNames() {
670
        List parameterNames = new ArrayList(getFormParameters().keySet());
1✔
671
        return (String[]) parameterNames.toArray(new String[parameterNames.size()]);
1✔
672
    }
673

674
    /**
675
     * Returns the multiple default values of the named parameter.
676
     **/
677
    @Override
678
    public String[] getParameterValues(String name) {
679
        final FormParameter parameter = getParameter(name);
1✔
680
        return parameter.getValues();
1✔
681
    }
682

683
    /**
684
     * Returns true if the named parameter is read-only. If more than one control exists with the same name, will return
685
     * true only if all such controls are read-only.
686
     *
687
     * @param name
688
     *            the name
689
     *
690
     * @return true, if is read only parameter
691
     */
692
    public boolean isReadOnlyParameter(String name) {
693
        return getParameter(name).isReadOnlyParameter();
1✔
694
    }
695

696
    /**
697
     * Returns true if the named parameter is disabled. If more than one control exists with the same name, will return
698
     * true only if all such controls are read-only.
699
     *
700
     * @param name
701
     *            the name
702
     *
703
     * @return true, if is disabled parameter
704
     */
705
    public boolean isDisabledParameter(String name) {
706
        return getParameter(name).isDisabledParameter();
1✔
707
    }
708

709
    /**
710
     * Returns true if the named parameter is hidden. If more than one control exists with the same name, will return
711
     * true only if all such controls are hidden.
712
     *
713
     * @param name
714
     *            the name
715
     *
716
     * @return true, if is hidden parameter
717
     */
718
    public boolean isHiddenParameter(String name) {
719
        return getParameter(name).isHiddenParameter();
1✔
720
    }
721

722
    /**
723
     * Creates and returns a web request which will simulate the submission of this form with an unnamed submit button.
724
     **/
725
    @Override
726
    public WebRequest getRequest() {
727
        return getRequest((SubmitButton) null);
1✔
728
    }
729

730
    /**
731
     * Creates and returns a web request based on the current state of this form. No parameter validation will be done
732
     * and there is no guarantee over the order of parameters transmitted.
733
     *
734
     * @return the web request
735
     */
736
    public WebRequest newUnvalidatedRequest() {
737
        return newUnvalidatedRequest(null);
1✔
738
    }
739

740
    /**
741
     * Records a parameter defined by including it in the destination URL. Ignores any parameters whose name matches a
742
     * form control.
743
     **/
744
    @Override
745
    protected void addPresetParameter(String name, String value) {
746
        FormControl[] formControls = getFormControls();
1✔
747
        for (FormControl formControl : formControls) {
1✔
748
            if (formControl.getName().equals(name)) {
1✔
749
                return;
1✔
750
            }
751
        }
752
        _presets.add(new PresetFormParameter(this, name, value));
1✔
753
    }
1✔
754

755
    @Override
756
    protected String getEmptyParameterValue() {
757
        return null;
1✔
758
    }
759

760
    // ---------------------------------- ParameterHolder methods
761
    // --------------------------------
762

763
    /**
764
     * Specifies the position at which an image button (if any) was clicked.
765
     **/
766
    @Override
767
    void selectImageButtonPosition(SubmitButton imageButton, int x, int y) {
768
        imageButton.setLocation(x, y);
1✔
769
    }
1✔
770

771
    /**
772
     * Iterates through the fixed, predefined parameters in this holder, recording them in the supplied parameter
773
     * processor.\ These parameters always go on the URL, no matter what encoding method is used.
774
     **/
775

776
    @Override
777
    void recordPredefinedParameters(ParameterProcessor processor) throws IOException {
778
        FormControl[] controls = getPresetParameters();
1✔
779
        for (FormControl control : controls) {
1✔
780
            control.addValues(processor, getCharacterSet());
1✔
781
        }
782
    }
1✔
783

784
    /**
785
     * Iterates through the parameters in this holder, recording them in the supplied parameter processor.
786
     **/
787
    @Override
788
    public void recordParameters(ParameterProcessor processor) throws IOException {
789
        FormControl[] controls = getFormControls();
1✔
790
        for (FormControl control : controls) {
1✔
791
            control.addValues(processor, getCharacterSet());
1✔
792
        }
793
    }
1✔
794

795
    /**
796
     * Removes a parameter name from this collection.
797
     **/
798
    @Override
799
    public void removeParameter(String name) {
800
        setParameter(name, NO_VALUES);
1✔
801
    }
1✔
802

803
    /**
804
     * Sets the value of a parameter in this form.
805
     *
806
     * @param name
807
     *            - the name of the parameter
808
     * @param value
809
     *            - the value of the parameter
810
     **/
811
    @Override
812
    public void setParameter(String name, String value) {
813
        setParameter(name, new String[] { value });
1✔
814
    }
1✔
815

816
    /**
817
     * Sets the multiple values of a parameter in this form. This is generally used when there are multiple controls
818
     * with the same name in the form.
819
     *
820
     * @param name
821
     *            the name
822
     * @param values
823
     *            the values
824
     */
825
    @Override
826
    public void setParameter(String name, final String[] values) {
827
        FormParameter parameter = getParameter(name);
1✔
828
        if (parameter.isUnknown()) {
1✔
829
            throw new NoSuchParameterException(name);
1✔
830
        }
831
        if (parameter.isFileParameter()) {
1✔
832
            if (values != NO_VALUES) {
1✔
833
                throw new InvalidFileParameterException(name, values);
1✔
834
            }
835
            parameter.setFiles(new UploadFileSpec[0]);
1✔
836
        } else {
837
            parameter.setValues(values);
1✔
838
        }
839

840
    }
1✔
841

842
    /**
843
     * Sets the multiple values of a file upload parameter in a web request.
844
     **/
845
    @Override
846
    public void setParameter(String name, UploadFileSpec[] files) {
847
        FormParameter parameter = getParameter(name);
1✔
848
        if (parameter == null || !parameter.isFileParameter()) {
1!
849
            throw new NoSuchParameterException(name);
1✔
850
        }
851
        parameter.setFiles(files);
1✔
852
    }
1✔
853

854
    /**
855
     * Sets the single value of a file upload parameter in this form. A more convenient way to do this than using
856
     * {@link #setParameter(String,com.meterware.httpunit.protocol.UploadFileSpec[])}
857
     *
858
     * @param name
859
     *            the name
860
     * @param file
861
     *            the file
862
     */
863
    public void setParameter(String name, File file) {
864
        setParameter(name, new UploadFileSpec[] { new UploadFileSpec(file) });
1✔
865
    }
1✔
866

867
    /**
868
     * Toggles the value of the specified checkbox parameter.
869
     *
870
     * @param name
871
     *            the name of the checkbox parameter
872
     *
873
     * @throws IllegalArgumentException
874
     *             if the specified parameter is not a checkbox or there is more than one control with that name.
875
     */
876
    public void toggleCheckbox(String name) {
877
        FormParameter parameter = getParameter(name);
1✔
878
        if (parameter == null) {
1!
879
            throw new NoSuchParameterException(name);
×
880
        }
881
        parameter.toggleCheckbox();
1✔
882
    }
1✔
883

884
    /**
885
     * Toggles the value of the specified checkbox parameter.
886
     *
887
     * @param name
888
     *            the name of the checkbox parameter
889
     * @param value
890
     *            of the checkbox parameter
891
     *
892
     * @throws IllegalArgumentException
893
     *             if the specified parameter is not a checkbox or if there is no checkbox with the specified name and
894
     *             value.
895
     */
896
    public void toggleCheckbox(String name, String value) {
897
        FormParameter parameter = getParameter(name);
1✔
898
        if (parameter == null) {
1!
899
            throw new NoSuchParameterException(name);
×
900
        }
901
        parameter.toggleCheckbox(value);
1✔
902
    }
1✔
903

904
    /**
905
     * Sets the value of the specified checkbox parameter.
906
     *
907
     * @param name
908
     *            the name of the checkbox parameter
909
     * @param state
910
     *            the new state of the checkbox
911
     *
912
     * @throws IllegalArgumentException
913
     *             if the specified parameter is not a checkbox or there is more than one control with that name.
914
     */
915
    public void setCheckbox(String name, boolean state) {
916
        FormParameter parameter = getParameter(name);
1✔
917
        if (parameter == null) {
1!
918
            throw new NoSuchParameterException(name);
×
919
        }
920
        parameter.setValue(state);
1✔
921
    }
1✔
922

923
    /**
924
     * Sets the value of the specified checkbox parameter.
925
     *
926
     * @param name
927
     *            the name of the checkbox parameter
928
     * @param value
929
     *            of the checkbox parameter
930
     * @param state
931
     *            the new state of the checkbox
932
     *
933
     * @throws IllegalArgumentException
934
     *             if the specified parameter is not a checkbox or if there is no checkbox with the specified name and
935
     *             value.
936
     */
937
    public void setCheckbox(String name, String value, boolean state) {
938
        FormParameter parameter = getParameter(name);
1✔
939
        if (parameter == null) {
1!
940
            throw new NoSuchParameterException(name);
×
941
        }
942
        parameter.setValue(value, state);
1✔
943
    }
1✔
944

945
    /**
946
     * Scriptable implementation for the WebForm.
947
     */
948
    public class Scriptable extends HTMLElementScriptable implements NamedDelegate, IdentifiedDelegate, FormScriptable {
949

950
        /**
951
         * Gets the action.
952
         *
953
         * @return the action
954
         */
955
        public String getAction() {
956
            return WebForm.this.getAction();
1✔
957
        }
958

959
        @Override
960
        public void setAction(String newAction) {
961
            setDestination(newAction);
1✔
962
            _presetParameters = null;
1✔
963
        }
1✔
964

965
        /**
966
         * Submit.
967
         *
968
         * @throws IOException
969
         *             Signals that an I/O exception has occurred.
970
         * @throws SAXException
971
         *             the SAX exception
972
         */
973
        public void submit() throws IOException, SAXException {
974
            submitRequest(getScriptedSubmitRequest());
1✔
975
        }
1✔
976

977
        /**
978
         * Reset.
979
         *
980
         * @throws IOException
981
         *             Signals that an I/O exception has occurred.
982
         * @throws SAXException
983
         *             the SAX exception
984
         */
985
        public void reset() throws IOException, SAXException {
986
            resetControls();
1✔
987
        }
1✔
988

989
        /**
990
         * return the name of the WebForm
991
         *
992
         * @return the name
993
         */
994
        @Override
995
        public String getName() {
996
            return WebForm.this.getName().length() != 0 ? WebForm.this.getName() : WebForm.this.getID();
1✔
997
        }
998

999
        /**
1000
         * return the id of the WebForm
1001
         *
1002
         * @return the id
1003
         */
1004
        @Override
1005
        public String getID() {
1006
            return WebForm.this.getID();
1✔
1007
        }
1008

1009
        /**
1010
         * get the Object for the given propertyName
1011
         *
1012
         * @param propertyName
1013
         *            - the name of the property to get
1014
         *
1015
         * @return the Object for the property
1016
         */
1017
        @Override
1018
        public Object get(String propertyName) {
1019
            if (propertyName.equals("target")) {
1✔
1020
                return getTarget();
1✔
1021
            }
1022
            if (propertyName.equals("action")) {
1✔
1023
                return getAction();
1✔
1024
            }
1025
            if (propertyName.equals("length")) {
1✔
1026
                return Integer.valueOf(getFormControls().length);
1✔
1027
            }
1028
            final FormParameter parameter = getParameter(propertyName);
1✔
1029
            if (!parameter.isUnknown()) {
1✔
1030
                return parameter.getScriptableObject();
1✔
1031
            }
1032
            FormControl control = getControlWithID(propertyName);
1✔
1033
            return control == null ? super.get(propertyName) : control.getScriptingHandler();
1✔
1034
        }
1035

1036
        /**
1037
         * Sets the value of the named property. Will throw a runtime exception if the property does not exist or cannot
1038
         * accept the specified value.
1039
         *
1040
         * @param propertyName
1041
         *            - the name of the property
1042
         * @param value
1043
         *            - the new value
1044
         **/
1045
        @Override
1046
        public void set(String propertyName, Object value) {
1047
            if (propertyName.equals("target")) {
1✔
1048
                setTargetAttribute(value.toString());
1✔
1049
            } else if (propertyName.equals("action")) {
1✔
1050
                setAction(value.toString());
1✔
1051
            } else if (propertyName.equals("name")) {
1✔
1052
                getElement().setAttribute("name", value.toString());
1✔
1053
            } else if (value instanceof String) {
1!
1054
                setParameterValue(propertyName, (String) value);
×
1055
            } else if (value instanceof Number) {
1!
1056
                setParameterValue(propertyName, HttpUnitUtils.trimmedValue((Number) value));
1✔
1057
            } else {
1058
                super.set(propertyName, value);
×
1059
            }
1060
        }
1✔
1061

1062
        @Override
1063
        public void setParameterValue(String name, String value) {
1064
            final Object scriptableObject = getParameter(name).getScriptableObject();
1✔
1065
            if (scriptableObject instanceof ScriptableDelegate) {
1!
1066
                ((ScriptableDelegate) scriptableObject).set("value", value);
1✔
1067
            } else if (scriptableObject instanceof ScriptableDelegate[]) {
×
1068
                ((ScriptableDelegate[]) scriptableObject)[0].set("value", value);
×
1069
            }
1070
        }
1✔
1071

1072
        /**
1073
         * Gets the element delegates.
1074
         *
1075
         * @return the element delegates
1076
         */
1077
        public ScriptableDelegate[] getElementDelegates() {
1078
            FormControl[] controls = getFormControls();
1✔
1079
            ScriptableDelegate[] result = new ScriptableDelegate[controls.length];
1✔
1080
            for (int i = 0; i < result.length; i++) {
1✔
1081
                result[i] = (ScriptableDelegate) controls[i].getScriptingHandler();
1✔
1082
            }
1083
            return result;
1✔
1084
        }
1085

1086
        /**
1087
         * Gets the elements by tag name.
1088
         *
1089
         * @param name
1090
         *            the name
1091
         *
1092
         * @return the elements by tag name
1093
         *
1094
         * @throws SAXException
1095
         *             the SAX exception
1096
         */
1097
        public ScriptableDelegate[] getElementsByTagName(String name) throws SAXException {
1098
            return getDelegates(getHTMLPage().getElementsByTagName(getElement(), name));
1✔
1099
        }
1100

1101
        /**
1102
         * Instantiates a new scriptable.
1103
         */
1104
        Scriptable() {
1✔
1105
            super(WebForm.this);
1✔
1106
        }
1✔
1107
    }
1108

1109
    // ---------------------------------- package members
1110
    // --------------------------------
1111

1112
    /**
1113
     * Contructs a web form given the URL of its source page and the DOM extracted from that page.
1114
     *
1115
     * @param response
1116
     *            the response
1117
     * @param baseURL
1118
     *            the base URL
1119
     * @param node
1120
     *            the node
1121
     * @param frame
1122
     *            the frame
1123
     * @param defaultTarget
1124
     *            the default target
1125
     * @param characterSet
1126
     *            the character set
1127
     * @param registry
1128
     *            the registry
1129
     */
1130
    WebForm(WebResponse response, URL baseURL, Node node, FrameSelector frame, String defaultTarget,
1131
            String characterSet, ElementRegistry registry) {
1132
        super(response, node, baseURL, "action", frame, defaultTarget);
1✔
1133
        _characterSet = characterSet;
1✔
1134
        _registry = registry;
1✔
1135
        _domElement = (HTMLFormElement) node;
1✔
1136
    }
1✔
1137

1138
    /**
1139
     * Returns the form control which is part of this form with the specified ID.
1140
     *
1141
     * @param id
1142
     *            the id
1143
     *
1144
     * @return the control with ID
1145
     */
1146
    public FormControl getControlWithID(String id) {
1147
        FormControl[] controls = getFormControls();
1✔
1148
        for (FormControl control : controls) {
1✔
1149
            if (control.getID().equals(id)) {
1✔
1150
                return control;
1✔
1151
            }
1152
        }
1153
        return null;
1✔
1154
    }
1155

1156
    // ---------------------------------- private members
1157
    // --------------------------------
1158

1159
    /**
1160
     * Gets the default button.
1161
     *
1162
     * @return the default button
1163
     */
1164
    private SubmitButton getDefaultButton() {
1165
        if (getSubmitButtons().length == 1) {
1✔
1166
            return getSubmitButtons()[0];
1✔
1167
        }
1168
        return getSubmitButton("");
1✔
1169
    }
1170

1171
    /**
1172
     * get the list of submit buttons - will always contain at least one button - if the original list has none a faked
1173
     * submit button will be added.
1174
     *
1175
     * @return a list with the submit buttons
1176
     */
1177
    private List<SubmitButton> getSubmitButtonVector() {
1178
        if (_buttonVector == null) {
1✔
1179
            _buttonVector = new ArrayList<>();
1✔
1180
            FormControl[] controls = getFormControls();
1✔
1181
            for (FormControl control : controls) {
1✔
1182
                if (control instanceof SubmitButton) {
1✔
1183
                    SubmitButton sb = (SubmitButton) control;
1✔
1184
                    sb.rememberEnableState();
1✔
1185
                    _buttonVector.add(sb);
1✔
1186
                }
1187
            }
1188

1189
            /**
1190
             * make sure that there is always at least one submit button if none is in the list add a faked one
1191
             */
1192
            if (_buttonVector.isEmpty()) {
1✔
1193
                _buttonVector.add(SubmitButton.createFakeSubmitButton(this));
1✔
1194
            }
1195
        }
1196
        return _buttonVector;
1✔
1197
    }
1198

1199
    /**
1200
     * Gets the preset parameters.
1201
     *
1202
     * @return the preset parameters
1203
     */
1204
    private FormControl[] getPresetParameters() {
1205
        if (_presetParameters == null) {
1✔
1206
            _presets = new ArrayList<>();
1✔
1207
            loadDestinationParameters();
1✔
1208
            _presetParameters = (FormControl[]) _presets.toArray(new FormControl[_presets.size()]);
1✔
1209
        }
1210
        return _presetParameters;
1✔
1211
    }
1212

1213
    /**
1214
     * New form control.
1215
     *
1216
     * @param child
1217
     *            the child
1218
     *
1219
     * @return the form control
1220
     */
1221
    FormControl newFormControl(Node child) {
1222
        return FormControl.newFormParameter(this, child);
1✔
1223
    }
1224

1225
    /**
1226
     * Returns an array of form parameter attributes for this form.
1227
     *
1228
     * @return the form controls
1229
     */
1230
    private FormControl[] getFormControls() {
1231
        HTMLCollection controlElements = _domElement.getElements();
1✔
1232
        FormControl[] controls = new FormControl[controlElements.getLength()];
1✔
1233
        for (int i = 0; i < controls.length; i++) {
1✔
1234
            controls[i] = getControlForNode(controlElements.item(i));
1✔
1235
        }
1236
        return controls;
1✔
1237
    }
1238

1239
    /**
1240
     * Gets the control for node.
1241
     *
1242
     * @param node
1243
     *            the node
1244
     *
1245
     * @return the control for node
1246
     */
1247
    private FormControl getControlForNode(Node node) {
1248
        if (_registry.hasNode(node)) {
1!
1249
            return (FormControl) _registry.getRegisteredElement(node);
1✔
1250
        }
1251
        return (FormControl) _registry.registerElement(node, newFormControl(node));
×
1252
    }
1253

1254
    /**
1255
     * get the form parameter with the given name.
1256
     *
1257
     * @param name
1258
     *            the name
1259
     *
1260
     * @return the form parameter with this name
1261
     */
1262
    public FormParameter getParameter(String name) {
1263
        final FormParameter parameter = (FormParameter) getFormParameters().get(name);
1✔
1264
        return parameter != null ? parameter : FormParameter.getUNKNOWN_PARAMETER();
1✔
1265
    }
1266

1267
    /**
1268
     * Returns a map of parameter name to form parameter objects. Each form parameter object represents the set of form
1269
     * controls with a particular name. Unnamed parameters are ignored.
1270
     *
1271
     * @return the form parameters
1272
     */
1273
    private Map getFormParameters() {
1274
        Map formParameters = new HashMap<>();
1✔
1275
        loadFormParameters(formParameters, getPresetParameters());
1✔
1276
        loadFormParameters(formParameters, getFormControls());
1✔
1277
        return formParameters;
1✔
1278
    }
1279

1280
    /**
1281
     * Load form parameters.
1282
     *
1283
     * @param formParameters
1284
     *            the form parameters
1285
     * @param controls
1286
     *            the controls
1287
     */
1288
    private void loadFormParameters(Map formParameters, FormControl[] controls) {
1289
        for (FormControl control : controls) {
1✔
1290
            if (control.getName().isEmpty()) {
1✔
1291
                continue;
1✔
1292
            }
1293
            FormParameter parameter = (FormParameter) formParameters.get(control.getName());
1✔
1294
            if (parameter == null) {
1✔
1295
                parameter = new FormParameter();
1✔
1296
                formParameters.put(control.getName(), parameter);
1✔
1297
            }
1298
            parameter.addControl(control);
1✔
1299
        }
1300
    }
1✔
1301

1302
    static {
1303
        MATCH_NAME = (htmlElement, criteria) -> HttpUnitUtils.matches(((WebForm) htmlElement).getName(),
1✔
1304
                (String) criteria);
1305

1306
    }
1✔
1307

1308
    // ===========================---===== exception class
1309
    // NoSuchParameterException =========================================
1310

1311
    /**
1312
     * This exception is thrown on an attempt to set a file parameter to a non file type.
1313
     */
1314
    class InvalidFileParameterException extends IllegalRequestParameterException {
1315

1316
        /** The Constant serialVersionUID. */
1317
        private static final long serialVersionUID = 1L;
1318

1319
        /**
1320
         * construct a new InvalidFileParameterException for the given parameter name and value list.
1321
         *
1322
         * @param parameterName
1323
         *            the parameter name
1324
         * @param values
1325
         *            the values
1326
         */
1327
        InvalidFileParameterException(String parameterName, String[] values) {
1✔
1328
            _parameterName = parameterName;
1✔
1329
            _values = values;
1✔
1330
        }
1✔
1331

1332
        /**
1333
         * get the message for this exception
1334
         */
1335
        @Override
1336
        public String getMessage() {
1337
            StringBuilder valueList = new StringBuilder();
1✔
1338
            String delim = "";
1✔
1339
            for (String _value : _values) {
1✔
1340
                valueList.append(delim).append("'").append(_value).append("'");
1✔
1341
                delim = ", ";
1✔
1342
            }
1343
            return "The file parameter with the name '" + _parameterName
1✔
1344
                    + "' must have type File but the string values " + valueList.append(" where supplied").toString();
1✔
1345
        }
1346

1347
        /** The parameter name. */
1348
        private String _parameterName;
1349

1350
        /** The values. */
1351
        private String[] _values;
1352
    }
1353

1354
    /**
1355
     * This exception is thrown on an attempt to set a parameter to a value not permitted to it by the form.
1356
     **/
1357
    class NoSuchParameterException extends IllegalRequestParameterException {
1358

1359
        /** The Constant serialVersionUID. */
1360
        private static final long serialVersionUID = 1L;
1361

1362
        /**
1363
         * Instantiates a new no such parameter exception.
1364
         *
1365
         * @param parameterName
1366
         *            the parameter name
1367
         */
1368
        NoSuchParameterException(String parameterName) {
1✔
1369
            _parameterName = parameterName;
1✔
1370
        }
1✔
1371

1372
        @Override
1373
        public String getMessage() {
1374
            return "No parameter named '" + _parameterName + "' is defined in the form";
1✔
1375
        }
1376

1377
        /** The parameter name. */
1378
        private String _parameterName;
1379

1380
    }
1381

1382
    // ============================= exception class
1383
    // IllegalUnnamedSubmitButtonException
1384
    // ======================================
1385

1386
    /**
1387
     * This exception is thrown on an attempt to define a form request with a button not defined on that form.
1388
     **/
1389
    class IllegalUnnamedSubmitButtonException extends IllegalRequestParameterException {
1390

1391
        /** The Constant serialVersionUID. */
1392
        private static final long serialVersionUID = 1L;
1393

1394
        /**
1395
         * Instantiates a new illegal unnamed submit button exception.
1396
         */
1397
        IllegalUnnamedSubmitButtonException() {
1✔
1398
        }
1✔
1399

1400
        @Override
1401
        public String getMessage() {
1402
            return "This form has more than one submit button, none unnamed. You must specify the button to be used.";
×
1403
        }
1404

1405
    }
1406

1407
    // ============================= exception class
1408
    // IllegalSubmitButtonException ======================================
1409

1410
    /**
1411
     * This exception is thrown on an attempt to define a form request with a button not defined on that form.
1412
     **/
1413
    class IllegalSubmitButtonException extends IllegalRequestParameterException {
1414

1415
        /** The Constant serialVersionUID. */
1416
        private static final long serialVersionUID = 1L;
1417

1418
        /**
1419
         * Instantiates a new illegal submit button exception.
1420
         *
1421
         * @param button
1422
         *            the button
1423
         */
1424
        IllegalSubmitButtonException(SubmitButton button) {
1✔
1425
            _name = button.getName();
1✔
1426
            _value = button.getValue();
1✔
1427
        }
1✔
1428

1429
        /**
1430
         * Instantiates a new illegal submit button exception.
1431
         *
1432
         * @param name
1433
         *            the name
1434
         * @param value
1435
         *            the value
1436
         */
1437
        IllegalSubmitButtonException(String name, String value) {
1✔
1438
            _name = name;
1✔
1439
            _value = value;
1✔
1440
        }
1✔
1441

1442
        @Override
1443
        public String getMessage() {
1444
            return "Specified submit button (name=\"" + _name + "\" value=\"" + _value + "\") not part of this form.";
×
1445
        }
1446

1447
        /** The name. */
1448
        private String _name;
1449

1450
        /** The value. */
1451
        private String _value;
1452

1453
    }
1454

1455
    // ============================= exception class
1456
    // IllegalUnnamedSubmitButtonException
1457
    // ======================================
1458

1459
}
1460

1461
// ========================================== class PresetFormParameter
1462
// =================================================
1463

1464
class PresetFormParameter extends FormControl {
1465

1466
    PresetFormParameter(WebForm form, String name, String value) {
1467
        super(form);
1✔
1468
        _name = name;
1✔
1469
        _value = value;
1✔
1470
    }
1✔
1471

1472
    /**
1473
     * Returns the name of this control..
1474
     **/
1475
    @Override
1476
    public String getName() {
1477
        return _name;
1✔
1478
    }
1479

1480
    /**
1481
     * Returns true if this control is read-only.
1482
     **/
1483
    @Override
1484
    public boolean isReadOnly() {
1485
        return true;
×
1486
    }
1487

1488
    /**
1489
     * Returns true if this control accepts free-form text.
1490
     **/
1491
    @Override
1492
    public boolean isTextControl() {
1493
        return true;
×
1494
    }
1495

1496
    /**
1497
     * Remove any required values for this control from the list, throwing an exception if they are missing.
1498
     **/
1499
    @Override
1500
    void claimRequiredValues(List values) {
1501
        if (_value != null) {
×
1502
            claimValueIsRequired(values, _value);
×
1503
        }
1504
    }
×
1505

1506
    @Override
1507
    public String getType() {
1508
        return UNDEFINED_TYPE;
×
1509
    }
1510

1511
    /**
1512
     * Returns the current value(s) associated with this control. These values will be transmitted to the server if the
1513
     * control is 'successful'.
1514
     **/
1515
    @Override
1516
    public String[] getValues() {
1517
        if (_values == null) {
×
1518
            _values = new String[] { _value };
×
1519
        }
1520
        return _values;
×
1521
    }
1522

1523
    @Override
1524
    protected void addValues(ParameterProcessor processor, String characterSet) throws IOException {
1525
        processor.addParameter(_name, _value, characterSet);
1✔
1526
    }
1✔
1527

1528
    private String _name;
1529
    private String _value;
1530
    private String[] _values;
1531
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc