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

xmlunit / xmlunit / cd160610-9b67-4752-a2c4-e3a0d82d991e

21 Apr 2025 11:55AM UTC coverage: 91.756% (-0.02%) from 91.78%
cd160610-9b67-4752-a2c4-e3a0d82d991e

push

circleci

web-flow
Merge pull request #289 from xmlunit/circleci-project-setup

CircleCI project setup

3996 of 4698 branches covered (85.06%)

11754 of 12810 relevant lines covered (91.76%)

2.35 hits per line

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

97.81
/xmlunit-core/src/main/java/org/xmlunit/diff/ElementSelectors.java
1
/*
2
  This file is licensed to You under the Apache License, Version 2.0
3
  (the "License"); you may not use this file except in compliance with
4
  the License.  You may obtain a copy of the License at
5

6
  http://www.apache.org/licenses/LICENSE-2.0
7

8
  Unless required by applicable law or agreed to in writing, software
9
  distributed under the License is distributed on an "AS IS" BASIS,
10
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
  See the License for the specific language governing permissions and
12
  limitations under the License.
13
*/
14
package org.xmlunit.diff;
15

16
import static org.xmlunit.util.Linqy.all;
17
import static org.xmlunit.util.Linqy.any;
18

19
import java.util.Arrays;
20
import java.util.Collection;
21
import java.util.HashMap;
22
import java.util.HashSet;
23
import java.util.Map;
24
import javax.xml.namespace.QName;
25
import org.xmlunit.util.IsNullPredicate;
26
import org.xmlunit.util.Linqy;
27
import org.xmlunit.util.Mapper;
28
import org.xmlunit.util.Nodes;
29
import org.xmlunit.util.Predicate;
30
import org.xmlunit.xpath.JAXPXPathEngine;
31
import org.xmlunit.xpath.XPathEngine;
32
import org.w3c.dom.Attr;
33
import org.w3c.dom.Element;
34
import org.w3c.dom.Node;
35

36
/**
37
 * Common ElementSelector implementations.
38
 */
39
public final class ElementSelectors {
40

41
    /**
42
     * Always returns true, i.e. each element can be compared to each
43
     * other element.
44
     *
45
     * <p>Generally this means elements will be compared in document
46
     * order.</p>
47
     */
48
    public static final ElementSelector Default = new ElementSelector() {
1✔
49
            @Override
50
            public boolean canBeCompared(Element controlElement,
51
                                         Element testElement) {
52
                return true;
1✔
53
            }
54
        };
55

56
    /**
57
     * Elements with the same local name (and namespace URI - if any)
58
     * can be compared.
59
     */
60
    public static final ElementSelector byName = new ElementSelector() {
1✔
61
            @Override
62
            public boolean canBeCompared(Element controlElement,
63
                                         Element testElement) {
64
                return controlElement != null
1✔
65
                    && testElement != null
66
                    && bothNullOrEqual(Nodes.getQName(controlElement),
1✔
67
                                       Nodes.getQName(testElement));
1✔
68
            }
69
        };
70

71
    /**
72
     * Elements with the same local name (and namespace URI - if any)
73
     * and nested text (if any) can be compared.
74
     */
75
    public static final ElementSelector byNameAndText = new ElementSelector() {
1✔
76
            @Override
77
            public boolean canBeCompared(Element controlElement,
78
                                         Element testElement) {
79
                return byName.canBeCompared(controlElement, testElement)
1✔
80
                    && bothNullOrEqual(Nodes.getMergedNestedText(controlElement),
1✔
81
                                       Nodes.getMergedNestedText(testElement));
1✔
82
            }
83
        };
84

85
    /**
86
     * Elements with the same local name (and namespace URI - if any)
87
     * and attribute values for all attributes can be compared.
88
     *
89
     * <p>This {@code ElementSelector} doesn't know anything about a potentially configured attribute filter so may also
90
     * compare attributes that are excluded from comparison by the filter. Use {@link
91
     * #byNameAndAllAttributes(Predicate)} passing in your attribute filter if this causes problems.</p>
92
     */
93
    public static final ElementSelector byNameAndAllAttributes =
1✔
94
        byNameAndAllAttributes(new Predicate<Attr>() {
1✔
95
            @Override
96
            public boolean test(Attr a) {
97
                return true;
1✔
98
            }
99
        });
100

101
    /**
102
     * Elements with the same local name (and namespace URI - if any)
103
     * and attribute values for all attributes can be compared.
104
     *
105
     * @param attributeFilter filter to use when comparing attributes. Only attributes where the filter returns {@code
106
     * true} are considered.
107
     *
108
     * @since XMLUnit 2.10.0
109
     * @return an ElementSelector
110
     */
111
    public static final ElementSelector byNameAndAllAttributes(final Predicate<Attr> attributeFilter) {
112
        return new ElementSelector() {
1✔
113
            @Override
114
            public boolean canBeCompared(Element controlElement,
115
                                         Element testElement) {
116
                if (!byName.canBeCompared(controlElement, testElement)) {
1✔
117
                    return false;
1✔
118
                }
119
                Map<QName, String> cAttrs = Nodes.getAttributes(controlElement, attributeFilter);
1✔
120
                Map<QName, String> tAttrs = Nodes.getAttributes(testElement, attributeFilter);
1✔
121
                if (cAttrs.size() != tAttrs.size()) {
1✔
122
                    return false;
1✔
123
                }
124
                return mapsEqualForKeys(cAttrs, tAttrs, cAttrs.keySet());
1✔
125
            }
126
        };
127
    }
128

129
    /**
130
     * String Constants.
131
     */
132
    private static final String SELECTORS_MUST_NOT_BE_NULL = "selectors must not be null";
133
    private static final String ATTRIBUTES_MUST_NOT_CONTAIN_NULL_VALUES = "attributes must not contain null values";
134
    private static final String ATTRIBUTES_MUST_NOT_BE_NULL = "attributes must not be null";
135

136

137
    /**
138
     * Maps Nodes to their NodeInfo equivalent.
139
     */
140
    static final Mapper<Node, XPathContext.NodeInfo> TO_NODE_INFO =
1✔
141
        new Mapper<Node, XPathContext.NodeInfo>() {
1✔
142
            @Override
143
            public XPathContext.NodeInfo apply(Node n) {
144
                return new XPathContext.DOMNodeInfo(n);
1✔
145
            }
146
        };
147

148
    private ElementSelectors() { }
149

150
    /**
151
     * Elements with the same local name (and namespace URI - if any)
152
     * and attribute values for the given attribute names can be
153
     * compared.
154
     *
155
     * <p>Attributes are only searched for in the null namespace.</p>
156
     *
157
     * @param attribs the names of all attributes who's values must be the same
158
     * @return the ElementSelector
159
     */
160
    public static ElementSelector byNameAndAttributes(String... attribs) {
161
        if (attribs == null) {
1✔
162
            throw new IllegalArgumentException(ATTRIBUTES_MUST_NOT_BE_NULL);
1✔
163
        }
164
        if (any(Arrays.asList(attribs), new IsNullPredicate())) {
1✔
165
            throw new IllegalArgumentException(ATTRIBUTES_MUST_NOT_CONTAIN_NULL_VALUES);
1✔
166
        }
167
        QName[] qs = new QName[attribs.length];
1✔
168
        for (int i = 0; i < attribs.length; i++) {
1✔
169
            qs[i] = new QName(attribs[i]);
1✔
170
        }
171
        return byNameAndAttributes(qs);
1✔
172
    }
173

174
    /**
175
     * Elements with the same local name (and namespace URI - if any)
176
     * and attribute values for the given attribute names can be
177
     * compared.
178
     *
179
     * <p>Namespace URIs of attributes are those of the attributes on
180
     * the control element or the null namespace if they don't
181
     * exist.</p>
182
     *
183
     * @param attribs the names of all attributes who's values must be the same
184
     * @return the ElementSelector
185
     */
186
    public static ElementSelector
187
        byNameAndAttributesControlNS(final String... attribs) {
188

189
        if (attribs == null) {
1✔
190
            throw new IllegalArgumentException(ATTRIBUTES_MUST_NOT_BE_NULL);
1✔
191
        }
192
        final Collection<String> qs = Arrays.asList(attribs);
1✔
193
        if (any(qs, new IsNullPredicate())) {
1✔
194
            throw new IllegalArgumentException(ATTRIBUTES_MUST_NOT_CONTAIN_NULL_VALUES);
1✔
195
        }
196
        final HashSet<String> as = new HashSet<String>(qs);
1✔
197
        return new ElementSelector() {
1✔
198
            @Override
199
            public boolean canBeCompared(Element controlElement,
200
                                         Element testElement) {
201
                if (!byName.canBeCompared(controlElement, testElement)) {
1✔
202
                    return false;
1✔
203
                }
204
                Map<QName, String> cAttrs = Nodes.getAttributes(controlElement);
1✔
205
                Map<String, QName> qNameByLocalName =
1✔
206
                    new HashMap<String, QName>();
207
                for (QName q : cAttrs.keySet()) {
1✔
208
                    String local = q.getLocalPart();
1✔
209
                    if (as.contains(local)) {
1✔
210
                        qNameByLocalName.put(local, q);
1✔
211
                    }
212
                }
1✔
213
                for (String a : as) {
1✔
214
                    QName q = qNameByLocalName.get(a);
1✔
215
                    if (q == null) {
1✔
216
                        qNameByLocalName.put(a, new QName(a));
1✔
217
                    }
218
                }
1✔
219
                return mapsEqualForKeys(cAttrs,
1✔
220
                                        Nodes.getAttributes(testElement),
1✔
221
                                        qNameByLocalName.values());
1✔
222
            }
223
        };
224
    }
225

226
    /**
227
     * Elements with the same local name (and namespace URI - if any)
228
     * and attribute values for the given attribute names can be
229
     * compared.
230
     *
231
     * @param attribs the qualified names of all attributes who's values must be the same
232
     * @return the ElementSelector
233
     */
234
    public static ElementSelector byNameAndAttributes(final QName... attribs) {
235
        if (attribs == null) {
1✔
236
            throw new IllegalArgumentException(ATTRIBUTES_MUST_NOT_BE_NULL);
1✔
237
        }
238
        final Collection<QName> qs = Arrays.asList(attribs);
1✔
239
        if (any(qs, new IsNullPredicate())) {
1✔
240
            throw new IllegalArgumentException(ATTRIBUTES_MUST_NOT_CONTAIN_NULL_VALUES);
1✔
241
        }
242
        return new ElementSelector() {
1✔
243
            @Override
244
            public boolean canBeCompared(Element controlElement,
245
                                         Element testElement) {
246
                if (!byName.canBeCompared(controlElement, testElement)) {
1✔
247
                    return false;
1✔
248
                }
249
                return mapsEqualForKeys(Nodes.getAttributes(controlElement),
1✔
250
                                        Nodes.getAttributes(testElement),
1✔
251
                                        qs);
252
            }
253
        };
254
    }
255

256
    /**
257
     * Negates another ElementSelector.
258
     *
259
     * @param es the ElementSelector to negate
260
     * @return the ElementSelector
261
     */
262
    public static ElementSelector not(final ElementSelector es) {
263
        if (es == null) {
1✔
264
            throw new IllegalArgumentException("es must not be null");
1✔
265
        }
266
        return new ElementSelector() {
1✔
267
            @Override
268
            public boolean canBeCompared(Element controlElement,
269
                                         Element testElement) {
270
                return !es.canBeCompared(controlElement, testElement);
1✔
271
            }
272
        };
273
    }
274

275
    /**
276
     * Accepts two elements if at least one of the given ElementSelectors does.
277
     *
278
     * <p>There is an important difference between using {@link
279
     * ElementSelectors#or} to combine multiple {@link
280
     * ElementSelector}s and using {@link DefaultNodeMatcher}'s
281
     * constructor with multiple {@link ElementSelector}s:</p>
282
     *
283
     * <p>Consider {@link ElementSelector}s {@code e1} and {@code e2}
284
     * and two control and test nodes each.  Assume {@code e1} would
285
     * match the first control node to the second test node and vice
286
     * versa if used alone, while {@code e2} would match the nodes in
287
     * order (the first control node to the first test and so on).</p>
288
     *
289
     * <p>{@link ElementSelectors#or} creates a combined {@link
290
     * ElementSelector} that is willing to match the first control
291
     * node to both of the test nodes - and the same for the second
292
     * control node.  Since nodes are compared in order when possible
293
     * the result will be the same as running {@code e2} alone.</p>
294
     *
295
     * <p>{@link DefaultNodeMatcher} with two {@link ElementSelector}s
296
     * will consult the {@link ElementSelector}s separately and only
297
     * invoke {@code e2} if there are any nodes not matched by {@code
298
     * e1} at all.  In this case the result will be the same as
299
     * running {@code e1} alone.</p>
300
     *
301
     * @param selectors the ElementSelectors to combine
302
     * @return the ElementSelector
303
     */
304
    public static ElementSelector or(final ElementSelector... selectors) {
305
        if (selectors == null) {
1✔
306
            throw new IllegalArgumentException(SELECTORS_MUST_NOT_BE_NULL);
1✔
307
        }
308
        final Collection<ElementSelector> s = Arrays.asList(selectors);
1✔
309
        if (any(s, new IsNullPredicate())) {
1✔
310
            throw new IllegalArgumentException("selectors must not contain null values");
1✔
311
        }
312
        return new ElementSelector() {
1✔
313
            @Override
314
            public boolean canBeCompared(Element controlElement,
315
                                         Element testElement) {
316
                return any(s, new CanBeComparedPredicate(controlElement, testElement));
1✔
317
            }
318
        };
319
    }
320

321
    /**
322
     * Accepts two elements if all of the given ElementSelectors do.
323
     *
324
     * @param selectors the ElementSelectors to combine
325
     * @return the ElementSelector
326
     */
327
    public static ElementSelector and(final ElementSelector... selectors) {
328
        if (selectors == null) {
1✔
329
            throw new IllegalArgumentException(SELECTORS_MUST_NOT_BE_NULL);
1✔
330
        }
331
        final Collection<ElementSelector> s = Arrays.asList(selectors);
1✔
332
        if (any(s, new IsNullPredicate())) {
1✔
333
            throw new IllegalArgumentException("selectors must not contain null values");
1✔
334
        }
335
        return new ElementSelector() {
1✔
336
            @Override
337
            public boolean canBeCompared(Element controlElement,
338
                                         Element testElement) {
339
                return all(s,
1✔
340
                           new CanBeComparedPredicate(controlElement, testElement));
341
            }
342
        };
343
    }
344

345
    /**
346
     * Accepts two elements if exactly on of the given ElementSelectors does.
347
     *
348
     * @param es1 the first ElementSelector to combine
349
     * @param es2 the second ElementSelector to combine
350
     * @return the ElementSelector
351
     */
352
    public static ElementSelector xor(final ElementSelector es1,
353
                                      final ElementSelector es2) {
354
        if (es1 == null || es2 == null) {
1✔
355
            throw new IllegalArgumentException(SELECTORS_MUST_NOT_BE_NULL);
1✔
356
        }
357
        return new ElementSelector() {
1✔
358
            @Override
359
            public boolean canBeCompared(Element controlElement,
360
                                         Element testElement) {
361
                return es1.canBeCompared(controlElement, testElement)
1✔
362
                    ^ es2.canBeCompared(controlElement, testElement);
1✔
363
            }
364
        };
365
    }
366

367
    /**
368
     * Applies the wrapped ElementSelector's logic if and only if the
369
     * control element matches the given predicate.
370
     * @param predicate the predicate applied to the control element
371
     * @param es the ElementSelector to consult
372
     * @return the ElementSelector
373
     */
374
    public static ElementSelector conditionalSelector(final Predicate<? super Element> predicate,
375
                                                      final ElementSelector es) {
376

377
        if (predicate == null) {
1✔
378
            throw new IllegalArgumentException("predicate must not be null");
1✔
379
        }
380
        if (es == null) {
1✔
381
            throw new IllegalArgumentException("es must not be null");
1✔
382
        }
383
        return new ElementSelector() {
1✔
384
            @Override
385
            public boolean canBeCompared(Element controlElement,
386
                                         Element testElement) {
387
                return predicate.test(controlElement)
1✔
388
                    && es.canBeCompared(controlElement, testElement);
1✔
389
            }
390
        };
391
    }
392

393
    /**
394
     * Applies the wrapped ElementSelector's logic if and only if the
395
     * control element has the given (local) name.
396
     * @param expectedName expected name of the control element
397
     * @param es the ElementSelector to consult
398
     * @return the ElementSelector
399
     */
400
    public static ElementSelector selectorForElementNamed(final String expectedName,
401
                                                          final ElementSelector es) {
402
        if (expectedName == null) {
1✔
403
            throw new IllegalArgumentException("expectedName must not be null");
1✔
404
        }
405

406
        return conditionalSelector(elementNamePredicate(expectedName), es);
1✔
407
    }
408

409
    /**
410
     * Applies the wrapped ElementSelector's logic if and only if the
411
     * control element has the given name.
412
     * @param expectedName expected name of the control element
413
     * @param es the ElementSelector to consult
414
     * @return the ElementSelector
415
     */
416
    public static ElementSelector selectorForElementNamed(final QName expectedName,
417
                                                          final ElementSelector es) {
418
        if (expectedName == null) {
1✔
419
            throw new IllegalArgumentException("expectedName must not be null");
1✔
420
        }
421

422
        return conditionalSelector(elementNamePredicate(expectedName), es);
1✔
423
    }
424

425
    /**
426
     * Selects two elements as matching if the child elements selected
427
     * via XPath match using the given childSelector.
428
     *
429
     * <p>The xpath expression should yield elements.  Two elements
430
     * match if a DefaultNodeMatcher applied to the selected children
431
     * finds matching pairs for all children.</p>
432
     *
433
     * @param xpath XPath expression applied in the context of the
434
     * elements to chose from that selects the children to compare.
435
     * @param childSelector ElementSelector to apply to the selected children.
436
     * @return the ElementSelector
437
     */
438
    public static ElementSelector byXPath(String xpath, ElementSelector childSelector) {
439
        return byXPath(xpath, null, null, childSelector);
1✔
440
    }
441

442
    /**
443
     * Selects two elements as matching if the child elements selected
444
     * via XPath match using the given childSelector.
445
     *
446
     * <p>The xpath expression should yield elements.  Two elements
447
     * match if a DefaultNodeMatcher applied to the selected children
448
     * finds matching pairs for all children.</p>
449
     *
450
     * @param xpath XPath expression applied in the context of the
451
     * elements to chose from that selects the children to compare.
452
     * @param engine XPathEngine to use. If {@code null} a {@link
453
     * JAXPXPathEngine} with default configuration will be used.
454
     * @param childSelector ElementSelector to apply to the selected children.
455
     * @return the ElementSelector
456
     *
457
     * @since XMLUnit 2.9.1
458
     */
459
    public static ElementSelector byXPath(String xpath, XPathEngine engine,
460
                                          ElementSelector childSelector) {
461
        return byXPath(xpath, engine, null, childSelector);
1✔
462
    }
463

464
    /**
465
     * Selects two elements as matching if the child elements selected
466
     * via XPath match using the given childSelector.
467
     *
468
     * <p>The xpath expression should yield elements.  Two elements
469
     * match if a DefaultNodeMatcher applied to the selected children
470
     * finds matching pairs for all children.</p>
471
     *
472
     * @param xpath XPath expression applied in the context of the
473
     * elements to chose from that selects the children to compare.
474
     * @param prefix2Uri maps from prefix to namespace URI.
475
     * @param childSelector ElementSelector to apply to the selected children.
476
     * @return the ElementSelector
477
     */
478
    public static ElementSelector byXPath(final String xpath,
479
                                          Map<String, String> prefix2Uri,
480
                                          ElementSelector childSelector) {
481
        return byXPath(xpath, null, prefix2Uri, childSelector);
×
482
    }
483

484
    /**
485
     * Selects two elements as matching if the child elements selected
486
     * via XPath match using the given childSelector.
487
     *
488
     * <p>The xpath expression should yield elements.  Two elements
489
     * match if a DefaultNodeMatcher applied to the selected children
490
     * finds matching pairs for all children.</p>
491
     *
492
     * @param xpath XPath expression applied in the context of the
493
     * elements to chose from that selects the children to compare.
494
     * @param xpathEngine XPathEngine to use. If {@code null} a {@link
495
     * JAXPXPathEngine} with default configuration will be used.
496
     * @param prefix2Uri maps from prefix to namespace URI.
497
     * @param childSelector ElementSelector to apply to the selected children.
498
     * @return the ElementSelector
499
     *
500
     * @since XMLUnit 2.9.1
501
     */
502
    public static ElementSelector byXPath(final String xpath,
503
                                          XPathEngine xpathEngine,
504
                                          Map<String, String> prefix2Uri,
505
                                          ElementSelector childSelector) {
506
        final XPathEngine engine =
507
            xpathEngine != null ? xpathEngine : new JAXPXPathEngine();
1✔
508
        if (prefix2Uri != null) {
1!
509
            engine.setNamespaceContext(prefix2Uri);
×
510
        }
511
        final NodeMatcher nm = new DefaultNodeMatcher(childSelector);
1✔
512
        return new ElementSelector() {
1✔
513
            @Override
514
            public boolean canBeCompared(Element controlElement,
515
                                         Element testElement) {
516
                Iterable<Node> controlChildren = engine.selectNodes(xpath, controlElement);
1✔
517
                int expected = Linqy.count(controlChildren);
1✔
518
                int matched =
1✔
519
                    Linqy.count(nm.match(controlChildren,
1✔
520
                                         engine.selectNodes(xpath, testElement)));
1✔
521
                return expected == matched;
1✔
522
            }
523
        };
524
    }
525

526
    /**
527
     * {@code then}-part of conditional {@link ElementSelectors} built
528
     * via {@link ConditionalSelectorBuilder}.
529
     */
530
    public interface ConditionalSelectorBuilderThen {
531
        /**
532
         * Specifies the ElementSelector to use when the condition holds true.
533
         * @param es the ElementSelector to use
534
         * @return the original builder
535
         */
536
        ConditionalSelectorBuilder thenUse(ElementSelector es);
537
    }
538

539
    /**
540
     * Allows to build complex {@link ElementSelector}s by combining simpler blocks.
541
     *
542
     * <p>All {@code when*}s are consulted in order and if one returns
543
     * {@code true} then the associated {@code ElementSelector} is
544
     * used.  If all of the, return {@code false}, the default set up
545
     * with {@code elseUse} if any is used.</p>
546
     */
547
    public interface ConditionalSelectorBuilder {
548
        /**
549
         * Sets up a conditional ElementSelector.
550
         * @param predicate the condition that must hold true
551
         * @return a then-part setting up the ElementSelector to use
552
         */
553
        ConditionalSelectorBuilderThen when(Predicate<? super Element> predicate);
554
        /**
555
         * Sets up a conditional ElementSelector.
556
         * @param expectedName expected name of the control element
557
         * @return a then-part setting up the ElementSelector to use
558
         */
559
        ConditionalSelectorBuilderThen whenElementIsNamed(String expectedName);
560
        /**
561
         * Sets up a conditional ElementSelector.
562
         * @param expectedName expected name of the control element
563
         * @return a then-part setting up the ElementSelector to use
564
         */
565
        ConditionalSelectorBuilderThen whenElementIsNamed(QName expectedName);
566
        /**
567
         * Assigns a default ElementSelector that is used if all
568
         * {@code when}s have returned false.
569
         * @param es the default ElementSelector to fall back to
570
         * @return the builder
571
         */
572
        ConditionalSelectorBuilder elseUse(ElementSelector es);
573
        /**
574
         * Builds a conditional ElementSelector.
575
         * @return an ElementSelector adhering to the ocnfigured conditions.
576
         */
577
        ElementSelector build();
578
    }
579

580
    /**
581
     * Allows to build complex {@link ElementSelector}s by combining simpler blocks.
582
     *
583
     * <p>All pairs created by the {@code when*}/{@code thenUse} pairs
584
     * are evaluated in order until one returns true, finally the
585
     * {@code default}, if any, is consulted.</p>
586
     *
587
     * @return a builder for conditional ElementSelectors
588
     */
589
    public static ConditionalSelectorBuilder conditionalBuilder() {
590
        return new DefaultConditionalSelectorBuilder();
1✔
591
    }
592

593
    private static boolean bothNullOrEqual(Object o1, Object o2) {
594
        return o1 == null ? o2 == null : o1.equals(o2);
1✔
595
    }
596

597
    private static boolean mapsEqualForKeys(Map<QName, String> control,
598
                                            Map<QName, String> test,
599
                                            Iterable<QName> keys) {
600
        for (QName q : keys) {
1✔
601
            if (!bothNullOrEqual(control.get(q), test.get(q))) {
1✔
602
                return false;
1✔
603
            }
604
        }
1✔
605
        return true;
1✔
606
    }
607

608
    static Predicate<Element> elementNamePredicate(final String expectedName) {
609
        return new Predicate<Element>() {
1✔
610
            @Override
611
            public boolean test(Element e) {
612
                if (e == null) {
1!
613
                    return false;
×
614
                }
615
                String name = e.getLocalName();
1✔
616
                if (name == null) {
1✔
617
                    name = e.getNodeName();
1✔
618
                }
619
                return expectedName.equals(name);
1✔
620
            }
621
        };
622
    }
623

624
    static Predicate<Element> elementNamePredicate(final QName expectedName) {
625
        return new Predicate<Element>() {
1✔
626
            @Override
627
            public boolean test(Element e) {
628
                return e != null && expectedName.equals(Nodes.getQName(e));
1!
629
            }
630
        };
631
    }
632

633
    private static class CanBeComparedPredicate implements Predicate<ElementSelector> {
634
        private final Element e1;
635
        private final Element e2;
636

637
        private CanBeComparedPredicate(Element e1, Element e2) {
1✔
638
            this.e1 = e1;
1✔
639
            this.e2 = e2;
1✔
640
        }
1✔
641

642
        @Override
643
        public boolean test(ElementSelector es) {
644
            return es.canBeCompared(e1, e2);
1✔
645
        }
646
    }
647

648
}
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

© 2025 Coveralls, Inc