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

hazendaz / httpunit / 636

05 Dec 2025 03:27AM UTC coverage: 80.509%. Remained the same
636

push

github

hazendaz
Cleanup more old since tags

you guessed it, at this point going to jautodoc the rest so the warnings on builds go away ;)

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8249 of 10132 relevant lines covered (81.42%)

0.81 hits per line

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

63.52
/src/main/java/com/meterware/httpunit/HttpUnitOptions.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.parsing.HTMLParserFactory;
23
import com.meterware.httpunit.parsing.HTMLParserListener;
24
import com.meterware.httpunit.scripting.ScriptableDelegate;
25
import com.meterware.httpunit.scripting.ScriptingEngineFactory;
26
import com.meterware.httpunit.scripting.ScriptingHandler;
27

28
import java.lang.reflect.InvocationTargetException;
29
import java.nio.charset.StandardCharsets;
30
import java.util.HashSet;
31
import java.util.Set;
32
import java.util.Vector;
33

34
/**
35
 * A collection of global options to control HttpUnit's behavior.
36
 **/
37
public abstract class HttpUnitOptions {
×
38
    public static final String ORIGINAL_SCRIPTING_ENGINE_FACTORY = "com.meterware.httpunit.javascript.JavaScriptEngineFactory";
39
    // comment out the scripting engine not to be used by allowing the appropriate number of asterisks in the comment on
40
    // the next line (1 or 2)
41
    /**/
42
    public static final String DEFAULT_SCRIPT_ENGINE_FACTORY = ORIGINAL_SCRIPTING_ENGINE_FACTORY;
43
    /*
44
     * / public static final String DEFAULT_SCRIPT_ENGINE_FACTORY = NEW_SCRIPTING_ENGINE_FACTORY; /
45
     */
46

47
    /**
48
     * Resets all options to their default values.
49
     */
50
    public static void reset() {
51
        _exceptionsOnErrorStatus = true;
1✔
52
        _parameterValuesValidated = true;
1✔
53
        _imagesTreatedAsAltText = false;
1✔
54
        _loggingHttpHeaders = false;
1✔
55
        _matchesIgnoreCase = true;
1✔
56
        _checkContentLength = false;
1✔
57
        _redirectDelay = 0; // TODO move this to ClientProperties
1✔
58
        _characterSet = StandardCharsets.ISO_8859_1.name();
1✔
59
        _contentType = DEFAULT_CONTENT_TYPE;
1✔
60
        _postIncludesCharset = false;
1✔
61
        _exceptionsThrownOnScriptError = true;
1✔
62
        _customAttributes = null;
1✔
63
        _javaScriptOptimizationLevel = -1;
1✔
64
        _checkHtmlContentType = false;
1✔
65
        setScriptEngineClassName(DEFAULT_SCRIPT_ENGINE_FACTORY);
1✔
66
        setScriptingEnabled(true);
1✔
67
    }
1✔
68

69
    /**
70
     * Returns true if HttpUnit is accepting and saving cookies. The default is to accept them.
71
     *
72
     * @deprecated as of 1.5.3, use ClientProperties#isAcceptCookies();
73
     */
74
    @Deprecated
75
    public static boolean isAcceptCookies() {
76
        return ClientProperties.getDefaultProperties().isAcceptCookies();
×
77
    }
78

79
    /**
80
     * Specifies whether HttpUnit should accept and send cookies.
81
     *
82
     * @deprecated as of 1.5.3, use ClientProperties#setAcceptCookies();
83
     */
84
    @Deprecated
85
    public static void setAcceptCookies(boolean acceptCookies) {
86
        ClientProperties.getDefaultProperties().setAcceptCookies(acceptCookies);
×
87
    }
×
88

89
    /**
90
     * Returns true if any WebClient created will accept GZIP encoding of responses. The default is to accept GZIP
91
     * encoding.
92
     *
93
     * @deprecated as of 1.5.3, use ClientProperties#isAcceptGzip();
94
     **/
95
    @Deprecated
96
    public static boolean isAcceptGzip() {
97
        return ClientProperties.getDefaultProperties().isAcceptGzip();
×
98
    }
99

100
    /**
101
     * Specifies whether a WebClient will be initialized to accept GZIP encoded responses. The default is true.
102
     *
103
     * @deprecated as of 1.5.3, use ClientProperties#setAcceptGzip();
104
     */
105
    @Deprecated
106
    public static void setAcceptGzip(boolean acceptGzip) {
107
        ClientProperties.getDefaultProperties().setAcceptGzip(acceptGzip);
×
108
    }
×
109

110
    /**
111
     * Resets the default character set to the HTTP default encoding.
112
     **/
113
    public static void resetDefaultCharacterSet() {
114
        _characterSet = StandardCharsets.ISO_8859_1.name();
×
115
    }
×
116

117
    /**
118
     * Resets the default content type to plain text.
119
     **/
120
    public static void resetDefaultContentType() {
121
        _contentType = DEFAULT_CONTENT_TYPE;
×
122
    }
×
123

124
    /**
125
     * Sets the default character set for pages which do not specify one and for requests created without HTML sources.
126
     * By default, HttpUnit uses the HTTP default encoding, ISO-8859-1.
127
     **/
128
    public static void setDefaultCharacterSet(String characterSet) {
129
        _characterSet = characterSet;
1✔
130
    }
1✔
131

132
    /**
133
     * Returns the character set to be used for pages which do not specify one.
134
     **/
135
    public static String getDefaultCharacterSet() {
136
        return _characterSet;
1✔
137
    }
138

139
    /**
140
     * Returns true if HttpUnit will throw an exception when a message is only partially received. The default is to
141
     * avoid such checks.
142
     */
143
    public static boolean isCheckContentLength() {
144
        return _checkContentLength;
1✔
145
    }
146

147
    /**
148
     * Specifies whether HttpUnit should throw an exception when the content length of a message does not match its
149
     * actual received length. Defaults to false.
150
     */
151
    public static void setCheckContentLength(boolean checkContentLength) {
152
        _checkContentLength = checkContentLength;
1✔
153
    }
1✔
154

155
    /**
156
     * Determines whether a normal POST request will include the character set in the content-type header. The default
157
     * is to include it; however, some older servlet engines (most notably Tomcat 3.1) get confused when they see it.
158
     **/
159
    public static void setPostIncludesCharset(boolean postIncludesCharset) {
160
        _postIncludesCharset = postIncludesCharset;
×
161
    }
×
162

163
    /**
164
     * Returns true if POST requests should include the character set in the content-type header.
165
     **/
166
    public static boolean isPostIncludesCharset() {
167
        return _postIncludesCharset;
1✔
168
    }
169

170
    /**
171
     * Sets the default content type for pages which do not specify one.
172
     **/
173
    public static void setDefaultContentType(String contentType) {
174
        _contentType = contentType;
×
175
    }
×
176

177
    /**
178
     * Returns the content type to be used for pages which do not specify one.
179
     **/
180
    public static String getDefaultContentType() {
181
        return _contentType;
×
182
    }
183

184
    /**
185
     * Returns true if parser warnings are enabled.
186
     *
187
     * @deprecated as of 1.5.2, use HTMLParserFactory#isParserWarningsEnabled
188
     **/
189
    @Deprecated
190
    public static boolean getParserWarningsEnabled() {
191
        return HTMLParserFactory.isParserWarningsEnabled();
×
192
    }
193

194
    /**
195
     * If true, tells the parser to display warning messages. The default is false (warnings are not shown).
196
     *
197
     * @deprecated as of 1.5.2, use HTMLParserFactory#setParserWarningsEnabled
198
     **/
199
    @Deprecated
200
    public static void setParserWarningsEnabled(boolean enabled) {
201
        HTMLParserFactory.setParserWarningsEnabled(enabled);
×
202
    }
×
203

204
    /**
205
     * If true, WebClient.getResponse throws an exception when it receives an error status. Defaults to true.
206
     **/
207
    public static void setExceptionsThrownOnErrorStatus(boolean enabled) {
208
        _exceptionsOnErrorStatus = enabled;
1✔
209
    }
1✔
210

211
    /**
212
     * Returns true if WebClient.getResponse throws exceptions when detected an error status.
213
     **/
214
    public static boolean getExceptionsThrownOnErrorStatus() {
215
        return _exceptionsOnErrorStatus;
1✔
216
    }
217

218
    /**
219
     * Returns true if form parameter settings are checked.
220
     *
221
     * @deprecated as of 1.6, use WebForm#newUnvalidatedRequest() to obtain a request without parameter validation.
222
     **/
223
    @Deprecated
224
    public static boolean getParameterValuesValidated() {
225
        return _parameterValuesValidated;
1✔
226
    }
227

228
    /**
229
     * If true, tells HttpUnit to throw an exception on any attempt to set a form parameter to a value which could not
230
     * be set via the browser. The default is true (parameters are validated).<br>
231
     * <b>Note:</b> this only applies to a WebRequest created after this setting is changed. A request created with this
232
     * option disabled will not only not be checked for correctness, its parameter submission order will not be
233
     * guaranteed, and changing parameters will not trigger Javascript onChange / onClick events.
234
     *
235
     * @deprecated as of 1.6, use WebForm#newUnvalidatedRequest() to obtain a request without parameter validation.
236
     **/
237
    @Deprecated
238
    public static void setParameterValuesValidated(boolean validated) {
239
        _parameterValuesValidated = validated;
1✔
240
    }
1✔
241

242
    /**
243
     * Returns true if images are treated as text, using their alt attributes.
244
     **/
245
    public static boolean getImagesTreatedAsAltText() {
246
        return _imagesTreatedAsAltText;
1✔
247
    }
248

249
    /**
250
     * If true, tells HttpUnit to treat images with alt attributes as though they were the text value of that attribute
251
     * in all searches and displays. The default is false (image text is generally ignored).
252
     **/
253
    public static void setImagesTreatedAsAltText(boolean asText) {
254
        _imagesTreatedAsAltText = asText;
1✔
255
    }
1✔
256

257
    /**
258
     * If true, text matches in methods such as {@link HTMLSegment#getLinkWith} are case insensitive. The default is
259
     * true (matches ignore case).
260
     **/
261
    public static boolean getMatchesIgnoreCase() {
262
        return _matchesIgnoreCase;
1✔
263
    }
264

265
    /**
266
     * If true, text matches in methods such as {@link HTMLSegment#getLinkWith} are case insensitive. The default is
267
     * true (matches ignore case).
268
     **/
269
    public static void setMatchesIgnoreCase(boolean ignoreCase) {
270
        _matchesIgnoreCase = ignoreCase;
×
271
    }
×
272

273
    /**
274
     * Returns true if HTTP headers are to be dumped to system output.
275
     **/
276
    public static boolean isLoggingHttpHeaders() {
277
        return _loggingHttpHeaders;
1✔
278
    }
279

280
    /**
281
     * If true, tells HttpUnit to log HTTP headers to system output. The default is false.
282
     **/
283
    public static void setLoggingHttpHeaders(boolean enabled) {
284
        _loggingHttpHeaders = enabled;
1✔
285
    }
1✔
286

287
    /**
288
     * Returns true if HttpUnit throws an exception when attempting to parse as HTML a response whose content type is
289
     * not HTML. The default is false (content type is ignored).
290
     **/
291
    public static boolean isCheckHtmlContentType() {
292
        return _checkHtmlContentType;
1✔
293
    }
294

295
    /**
296
     * If true, HttpUnit throws an exception when attempting to parse as HTML a response whose content type is not HTML.
297
     * The default is false (content type is ignored).
298
     **/
299
    public static void setCheckHtmlContentType(boolean checkHtmlContentType) {
300
        _checkHtmlContentType = checkHtmlContentType;
1✔
301
    }
1✔
302

303
    /**
304
     * Returns true if HttpUnit should automatically follow page redirect requests (status 3xx). By default, this is
305
     * true.
306
     *
307
     * @deprecated as of 1.5.3, use ClientProperties#isAutoRedirect();
308
     **/
309
    @Deprecated
310
    public static boolean getAutoRedirect() {
311
        return ClientProperties.getDefaultProperties().isAutoRedirect();
×
312
    }
313

314
    /**
315
     * Determines whether HttpUnit should automatically follow page redirect requests (status 3xx). By default, this is
316
     * true in order to simulate normal browser operation.
317
     *
318
     * @deprecated as of 1.5.3, use ClientProperties#setAutoRedirect();
319
     **/
320
    @Deprecated
321
    public static void setAutoRedirect(boolean autoRedirect) {
322
        ClientProperties.getDefaultProperties().setAutoRedirect(autoRedirect);
×
323
    }
×
324

325
    /**
326
     * Returns the delay, in milliseconds, before a redirect request is issues.
327
     **/
328
    public static int getRedirectDelay() {
329
        return _redirectDelay;
1✔
330
    }
331

332
    /**
333
     * Sets the delay, in milliseconds, before a redirect request is issued. This may be necessary if the server under
334
     * some cases where the server performs asynchronous processing which must be completed before the new request can
335
     * be handled properly, and is taking advantage of slower processing by most user agents. It almost always indicates
336
     * an error in the server design, and therefore the default delay is zero.
337
     **/
338
    public static void setRedirectDelay(int delayInMilliseconds) {
339
        _redirectDelay = delayInMilliseconds;
×
340
    }
×
341

342
    /**
343
     * Returns true if HttpUnit should automatically follow page refresh requests. By default, this is false, so that
344
     * programs can verify the redirect page presented to users before the browser switches to the new page.
345
     *
346
     * @deprecated as of 1.5.3, use ClientProperties#isAutoRefresh();
347
     **/
348
    @Deprecated
349
    public static boolean getAutoRefresh() {
350
        return ClientProperties.getDefaultProperties().isAutoRefresh();
×
351
    }
352

353
    /**
354
     * Specifies whether HttpUnit should automatically follow page refresh requests. By default, this is false, so that
355
     * programs can verify the redirect page presented to users before the browser switches to the new page. Setting
356
     * this to true can cause an infinite loop on pages that refresh themselves.
357
     *
358
     * @deprecated as of 1.5.3, use ClientProperties#setAutoRefresh();
359
     **/
360
    @Deprecated
361
    public static void setAutoRefresh(boolean autoRefresh) {
362
        ClientProperties.getDefaultProperties().setAutoRefresh(autoRefresh);
×
363
    }
×
364

365
    /**
366
     * Remove an Html error listener.
367
     *
368
     * @deprecated as of 1.5.2, use HTMLParserfactory#removeHTMLParserListener
369
     **/
370
    @Deprecated
371
    public static void removeHtmlErrorListener(HTMLParserListener el) {
372
        HTMLParserFactory.removeHTMLParserListener(el);
×
373
    }
×
374

375
    /**
376
     * Add an Html error listener.
377
     *
378
     * @deprecated as of 1.5.2, use HTMLParserfactory#addHTMLParserListener
379
     **/
380
    @Deprecated
381
    public static void addHtmlErrorListener(HTMLParserListener el) {
382
        HTMLParserFactory.addHTMLParserListener(el);
×
383
    }
×
384

385
    /**
386
     * Get the list of Html Error Listeners
387
     *
388
     * @deprecated as of 1.5.2, removed with no replacement
389
     **/
390
    @Deprecated
391
    public static Vector getHtmlErrorListeners() {
392
        return null;
×
393
    }
394

395
    public static String getScriptEngineClassName() {
396
        return _scriptEngineClassName;
×
397
    }
398

399
    public static void setScriptEngineClassName(String scriptEngineClassName) {
400
        if (_scriptEngineClassName == null || !_scriptEngineClassName.equals(scriptEngineClassName)) {
1!
401
            _scriptingEngine = null;
1✔
402
        }
403
        _scriptEngineClassName = scriptEngineClassName;
1✔
404
    }
1✔
405

406
    public static ScriptingEngineFactory getScriptingEngine() {
407
        if (_scriptingEngine == null) {
1✔
408
            try {
409
                Class factoryClass = Class.forName(_scriptEngineClassName);
1✔
410
                final ScriptingEngineFactory factory = (ScriptingEngineFactory) factoryClass.getDeclaredConstructor()
1✔
411
                        .newInstance();
1✔
412
                _scriptingEngine = factory.isEnabled() ? factory : NULL_SCRIPTING_ENGINE_FACTORY;
1!
413
                _scriptingEngine.setThrowExceptionsOnError(_exceptionsThrownOnScriptError);
1✔
414
            } catch (ClassNotFoundException e) {
×
415
                disableScripting(e, "Unable to find scripting engine factory class ");
×
416
            } catch (InstantiationException e) {
×
417
                disableScripting(e, "Unable to instantiate scripting engine factory class ");
×
418
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
×
419
                    | NoSuchMethodException | SecurityException e) {
420
                disableScripting(e, "Unable to create scripting engine factory class ");
×
421
            }
1✔
422
        }
423
        return _scriptingEngine;
1✔
424
    }
425

426
    /**
427
     * change the scriptingEnabled flag
428
     *
429
     * @param scriptingEnabled
430
     */
431
    public static void setScriptingEnabled(boolean scriptingEnabled) {
432
        if (scriptingEnabled != _scriptingEnabled) {
1✔
433
            _scriptingEngine = scriptingEnabled ? null : NULL_SCRIPTING_ENGINE_FACTORY;
1✔
434
        }
435
        _scriptingEnabled = scriptingEnabled;
1✔
436
    }
1✔
437

438
    public static boolean isScriptingEnabled() {
439
        return _scriptingEnabled;
1✔
440
    }
441

442
    /**
443
     * Determines whether script errors result in exceptions or warning messages.
444
     *
445
     * @return the current state
446
     */
447
    public static boolean setExceptionsThrownOnScriptError(boolean throwExceptions) {
448
        boolean current = _exceptionsThrownOnScriptError;
1✔
449
        _exceptionsThrownOnScriptError = throwExceptions;
1✔
450
        getScriptingEngine().setThrowExceptionsOnError(throwExceptions);
1✔
451
        return current;
1✔
452
    }
453

454
    /**
455
     * Returns true if script errors cause exceptions to be thrown.
456
     */
457
    public static boolean getExceptionsThrownOnScriptError() {
458
        return _exceptionsThrownOnScriptError;
1✔
459
    }
460

461
    /**
462
     * Returns the accumulated script error messages encountered. Error messages are accumulated only if
463
     * 'throwExceptionsOnError' is disabled.
464
     */
465
    public static String[] getScriptErrorMessages() {
466
        return getScriptingEngine().getErrorMessages();
1✔
467
    }
468

469
    /**
470
     * Clears the accumulated script error messages.
471
     */
472
    public static void clearScriptErrorMessages() {
473
        getScriptingEngine().clearErrorMessages();
1✔
474
    }
1✔
475

476
    private static void disableScripting(Exception e, String errorMessage) {
477
        System.err.println(errorMessage + _scriptEngineClassName);
×
478
        System.err.println("" + e);
×
479
        System.err.println("JavaScript execution disabled");
×
480
        _scriptingEngine = NULL_SCRIPTING_ENGINE_FACTORY;
×
481
    }
×
482

483
    // --------------------------------- private members --------------------------------------
484

485
    private static final String DEFAULT_CONTENT_TYPE = "text/html";
486

487
    private static final ScriptingEngineFactory NULL_SCRIPTING_ENGINE_FACTORY = new ScriptingEngineFactory() {
1✔
488
        @Override
489
        public boolean isEnabled() {
490
            return false;
×
491
        }
492

493
        @Override
494
        public void associate(WebResponse response) {
495
        }
1✔
496

497
        @Override
498
        public void load(WebResponse response) {
499
        }
1✔
500

501
        @Override
502
        public void setThrowExceptionsOnError(boolean throwExceptions) {
503
        }
×
504

505
        @Override
506
        public boolean isThrowExceptionsOnError() {
507
            return false;
×
508
        }
509

510
        @Override
511
        public String[] getErrorMessages() {
512
            return new String[0];
×
513
        }
514

515
        @Override
516
        public void clearErrorMessages() {
517
        }
×
518

519
        @Override
520
        public ScriptingHandler createHandler(HTMLElement element) {
521
            return ScriptableDelegate.NULL_SCRIPT_ENGINE;
1✔
522
        }
523

524
        @Override
525
        public ScriptingHandler createHandler(WebResponse response) {
526
            return ScriptableDelegate.NULL_SCRIPT_ENGINE;
×
527
        }
528

529
        @Override
530
        public void handleScriptException(Exception e, String badScript) {
531
            // happily ignore and exception
532
        }
×
533
    };
534

535
    /**
536
     * Add the name of a custom attribute that should be supported for form controls.
537
     *
538
     * @deprecated for new Scripting engine
539
     */
540
    @Deprecated
541
    public static void addCustomAttribute(String attributeName) {
542
        if (_customAttributes == null) {
1!
543
            _customAttributes = new HashSet<>();
1✔
544
        }
545
        _customAttributes.add(attributeName);
1✔
546
    }
1✔
547

548
    /**
549
     * Get the Set of custom attribute names to be supported by form controls.
550
     *
551
     * @deprecated for new scripting engine
552
     */
553
    @Deprecated
554
    static Set getCustomAttributes() {
555
        return _customAttributes;
1✔
556
    }
557

558
    private static Set _customAttributes = null;
1✔
559

560
    private static boolean _exceptionsOnErrorStatus = true;
1✔
561

562
    private static boolean _parameterValuesValidated = true;
1✔
563

564
    private static boolean _imagesTreatedAsAltText;
565

566
    private static boolean _loggingHttpHeaders;
567

568
    private static boolean _matchesIgnoreCase = true;
1✔
569

570
    private static boolean _postIncludesCharset = false;
1✔
571

572
    private static boolean _checkContentLength = false;
1✔
573

574
    private static int _redirectDelay;
575

576
    private static String _characterSet = StandardCharsets.ISO_8859_1.name();
1✔
577

578
    private static String _contentType = DEFAULT_CONTENT_TYPE;
1✔
579

580
    private static String _scriptEngineClassName;
581

582
    private static ScriptingEngineFactory _scriptingEngine;
583

584
    private static boolean _scriptingEnabled = true;
1✔
585

586
    private static boolean _exceptionsThrownOnScriptError = true;
1✔
587

588
    private static int _javaScriptOptimizationLevel = -1;
1✔
589

590
    private static boolean _checkHtmlContentType = false;
1✔
591

592
    static {
593
        reset();
1✔
594

595
    }
1✔
596

597
    /**
598
     * getter for Java Script optimization level
599
     *
600
     * @return the javaScriptOptimizationLevel to be use for running scripts
601
     */
602
    public static int getJavaScriptOptimizationLevel() {
603
        return _javaScriptOptimizationLevel;
1✔
604
    }
605

606
    /**
607
     * setter for Java Script optimization level
608
     *
609
     * @param scriptOptimizationLevel
610
     *            the _javaScriptOptimizationLevel to set see rhino documentation for valid values: -2: with
611
     *            continuation -1: interpret 0: compile to Java bytecode, don't optimize 1..9: compile to Java bytecode,
612
     *            optimize *
613
     */
614
    public static void setJavaScriptOptimizationLevel(int scriptOptimizationLevel) {
615
        _javaScriptOptimizationLevel = scriptOptimizationLevel;
×
616
    }
×
617
}
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