Best Karate code snippet using com.intuit.karate.MatchOperation
Source:MatchOperation.java  
...38/**39 *40 * @author pthomas341 */42public class MatchOperation {43    public static final String REGEX = "regex";44    final Match.Context context;45    final Match.Type type;46    final Match.Value actual;47    final Match.Value expected;48    final List<MatchOperation> failures;49    boolean pass = true;50    private String failReason;51    MatchOperation(Match.Type type, Match.Value actual, Match.Value expected) {52        this(JsEngine.global(), null, type, actual, expected);53    }54    MatchOperation(JsEngine js, Match.Type type, Match.Value actual, Match.Value expected) {55        this(js, null, type, actual, expected);56    }57    MatchOperation(Match.Context context, Match.Type type, Match.Value actual, Match.Value expected) {58        this(null, context, type, actual, expected);59    }60    private MatchOperation(JsEngine js, Match.Context context, Match.Type type, Match.Value actual, Match.Value expected) {61        this.type = type;62        this.actual = actual;63        this.expected = expected;64        if (context == null) {65            if (js == null) {66                js = JsEngine.global();67            }68            this.failures = new ArrayList();69            if (actual.isXml()) {70                this.context = new Match.Context(js, this, true, 0, "/", "", -1);71            } else {72                this.context = new Match.Context(js, this, false, 0, "$", "", -1);73            }74        } else {75            this.context = context;76            this.failures = context.root.failures;77        }78    }79    private Match.Type fromMatchEach() {80        switch (type) {81            case EACH_CONTAINS:82                return Match.Type.CONTAINS;83            case EACH_NOT_CONTAINS:84                return Match.Type.NOT_CONTAINS;85            case EACH_CONTAINS_ONLY:86                return Match.Type.CONTAINS_ONLY;87            case EACH_CONTAINS_ANY:88                return Match.Type.CONTAINS_ANY;89            case EACH_EQUALS:90                return Match.Type.EQUALS;91            case EACH_NOT_EQUALS:92                return Match.Type.NOT_EQUALS;93            case EACH_CONTAINS_DEEP:94                return Match.Type.CONTAINS_DEEP;95            default:96                throw new RuntimeException("unexpected outer match type: " + type);97        }98    }99    private static Match.Type macroToMatchType(boolean each, String macro) {100        if (macro.startsWith("^^")) {101            return each ? Match.Type.EACH_CONTAINS_ONLY : Match.Type.CONTAINS_ONLY;102        } else if (macro.startsWith("^+")) {103            return each ? Match.Type.EACH_CONTAINS_DEEP : Match.Type.CONTAINS_DEEP;104        } else if (macro.startsWith("^*")) {105            return each ? Match.Type.EACH_CONTAINS_ANY : Match.Type.CONTAINS_ANY;106        } else if (macro.startsWith("^")) {107            return each ? Match.Type.EACH_CONTAINS : Match.Type.CONTAINS;108        } else if (macro.startsWith("!^")) {109            return each ? Match.Type.EACH_NOT_CONTAINS : Match.Type.NOT_CONTAINS;110        } else if (macro.startsWith("!=")) {111            return each ? Match.Type.EACH_NOT_EQUALS : Match.Type.NOT_EQUALS;112        } else {113            return each ? Match.Type.EACH_EQUALS : Match.Type.EQUALS;114        }115    }116    private static int matchTypeToStartPos(Match.Type mt) {117        switch (mt) {118            case CONTAINS_ONLY:119            case EACH_CONTAINS_ONLY:120            case CONTAINS_DEEP:121            case EACH_CONTAINS_DEEP:122            case CONTAINS_ANY:123            case EACH_CONTAINS_ANY:124            case NOT_CONTAINS:125            case EACH_NOT_CONTAINS:126            case NOT_EQUALS:127            case EACH_NOT_EQUALS:128                return 2;129            case CONTAINS:130            case EACH_CONTAINS:131                return 1;132            default:133                return 0;134        }135    }136    boolean execute() {137        switch (type) {138            case EACH_CONTAINS:139            case EACH_NOT_CONTAINS:140            case EACH_CONTAINS_ONLY:141            case EACH_CONTAINS_ANY:142            case EACH_EQUALS:143            case EACH_NOT_EQUALS:144            case EACH_CONTAINS_DEEP:145                if (actual.isList()) {146                    List list = actual.getValue();147                    Match.Type nestedMatchType = fromMatchEach();148                    int count = list.size();149                    for (int i = 0; i < count; i++) {150                        Object o = list.get(i);151                        context.JS.put("_$", o);152                        MatchOperation mo = new MatchOperation(context.descend(i), nestedMatchType, new Match.Value(o), expected);153                        mo.execute();154                        context.JS.bindings.removeMember("_$");155                        if (!mo.pass) {156                            return fail("match each failed at index " + i);157                        }158                    }159                    // if we reached here all / each LHS items completed successfully160                    return true;161                } else {162                    return fail("actual is not an array or list");163                }164            default:165            // do nothing166        }167        if (actual.isNotPresent()) {168            if (!expected.isString() || !expected.getAsString().startsWith("#")) {169                return fail("actual path does not exist");170            }171        }172        if (actual.type != expected.type) {173            switch (type) {174                case CONTAINS:175                case NOT_CONTAINS:176                case CONTAINS_ANY:177                case CONTAINS_ONLY:178                case CONTAINS_DEEP:179                case CONTAINS_ANY_DEEP:180                    if (!expected.isList()) {181                        MatchOperation mo = new MatchOperation(context, type, actual, new Match.Value(Collections.singletonList(expected.getValue())));182                        mo.execute();183                        return mo.pass ? pass() : fail(mo.failReason);184                    }185                    break;186                default:187                // do nothing188            }189            if (expected.isXml() && actual.isMap()) {190                // special case, auto-convert rhs                191                MatchOperation mo = new MatchOperation(context, type, actual, new Match.Value(XmlUtils.toObject(expected.getValue(), true)));192                mo.execute();193                return mo.pass ? pass() : fail(mo.failReason);194            }195            if (expected.isString()) {196                String expStr = expected.getValue();197                if (!expStr.startsWith("#")) { // edge case if rhs is macro198                    return type == Match.Type.NOT_EQUALS ? pass() : fail("data types don't match");199                }200            } else {201                return type == Match.Type.NOT_EQUALS ? pass() : fail("data types don't match");202            }203        }204        if (expected.isString()) {205            String expStr = expected.getValue();206            if (expStr.startsWith("#")) {207                switch (type) {208                    case NOT_EQUALS:209                        return macroEqualsExpected(expStr) ? fail("is equal") : pass();210                    case NOT_CONTAINS:211                        return macroEqualsExpected(expStr) ? fail("actual contains expected") : pass();212                    default:213                        return macroEqualsExpected(expStr) ? pass() : fail(null);214                }215            }216        }217        switch (type) {218            case EQUALS:219                return actualEqualsExpected() ? pass() : fail("not equal");220            case NOT_EQUALS:221                return actualEqualsExpected() ? fail("is equal") : pass();222            case CONTAINS:223            case CONTAINS_ANY:224            case CONTAINS_ONLY:225            case CONTAINS_DEEP:226            case CONTAINS_ANY_DEEP:227                return actualContainsExpected() ? pass() : fail("actual does not contain expected");228            case NOT_CONTAINS:229                return actualContainsExpected() ? fail("actual contains expected") : pass();230            default:231                throw new RuntimeException("unexpected match type: " + type);232        }233    }234    private boolean macroEqualsExpected(String expStr) {235        boolean optional = expStr.startsWith("##");236        if (optional && actual.isNull()) { // exit early237            return true;238        }239        int minLength = optional ? 3 : 2;240        if (expStr.length() > minLength) {241            String macro = expStr.substring(minLength - 1);242            if (macro.startsWith("(") && macro.endsWith(")")) {243                macro = macro.substring(1, macro.length() - 1);244                Match.Type nestedType = macroToMatchType(false, macro);245                int startPos = matchTypeToStartPos(nestedType);246                macro = macro.substring(startPos);247                if (actual.isList()) { // special case, look for partial maps within list248                    if (nestedType == Match.Type.CONTAINS) {249                        nestedType = Match.Type.CONTAINS_DEEP;250                    } else if (nestedType == Match.Type.CONTAINS_ANY) {251                        nestedType = Match.Type.CONTAINS_ANY_DEEP;252                    }253                }254                context.JS.put("$", context.root.actual.getValue());255                context.JS.put("_", actual.getValue());256                JsValue jv = context.JS.eval(macro);257                context.JS.bindings.removeMember("$");258                context.JS.bindings.removeMember("_");259                MatchOperation mo = new MatchOperation(context, nestedType, actual, new Match.Value(jv.getValue()));260                return mo.execute();261            } else if (macro.startsWith("[")) {262                int closeBracketPos = macro.indexOf(']');263                if (closeBracketPos != -1) { // array, match each264                    if (!actual.isList()) {265                        return fail("actual is not an array");266                    }267                    if (closeBracketPos > 1) {268                        String bracketContents = macro.substring(1, closeBracketPos);269                        List listAct = actual.getValue();270                        int listSize = listAct.size();271                        context.JS.put("$", context.root.actual.getValue());272                        context.JS.put("_", listSize);273                        String sizeExpr;274                        if (bracketContents.indexOf('_') != -1) { // #[_ < 5] 275                            sizeExpr = bracketContents;276                        } else { // #[5] | #[$.foo] 277                            sizeExpr = bracketContents + " == _";278                        }279                        JsValue jv = context.JS.eval(sizeExpr);280                        context.JS.bindings.removeMember("$");281                        context.JS.bindings.removeMember("_");282                        if (!jv.isTrue()) {283                            return fail("actual array length is " + listSize);284                        }285                    }286                    if (macro.length() > closeBracketPos + 1) {287                        macro = StringUtils.trimToNull(macro.substring(closeBracketPos + 1));288                        if (macro != null) {289                            if (macro.startsWith("(") && macro.endsWith(")")) {290                                macro = macro.substring(1, macro.length() - 1); // strip parens291                            }292                            if (macro.startsWith("?")) { // #[]? _.length == 3293                                macro = "#" + macro;294                            }295                            if (macro.startsWith("#")) {296                                MatchOperation mo = new MatchOperation(context, Match.Type.EACH_EQUALS, actual, new Match.Value(macro));297                                mo.execute();298                                return mo.pass ? pass() : fail("all array elements matched");299                            } else { // schema reference300                                Match.Type nestedType = macroToMatchType(true, macro); // match each301                                int startPos = matchTypeToStartPos(nestedType);302                                macro = macro.substring(startPos);303                                JsValue jv = context.JS.eval(macro);304                                MatchOperation mo = new MatchOperation(context, nestedType, actual, new Match.Value(jv.getValue()));305                                return mo.execute();306                            }307                        }308                    }309                    return true; // expression within square brackets is ok310                }311            } else { // '#? _ != 0' | '#string' | '#number? _ > 0'312                int questionPos = macro.indexOf('?');313                String validatorName = null;314                // in case of regex we don't want to remove the '?'315                if (questionPos != -1 && !macro.startsWith(REGEX)) {316                    validatorName = macro.substring(0, questionPos);317                    if (macro.length() > questionPos + 1) {318                        macro = StringUtils.trimToEmpty(macro.substring(questionPos + 1));319                    } else {320                        macro = "";321                    }322                } else {323                    validatorName = macro;324                    macro = "";325                }326                validatorName = StringUtils.trimToNull(validatorName);327                if (validatorName != null) {328                    Match.Validator validator = null;329                    if (validatorName.startsWith(REGEX)) {330                        String regex = validatorName.substring(5).trim();331                        validator = new Match.RegexValidator(regex);332                    } else {333                        validator = Match.VALIDATORS.get(validatorName);334                    }335                    if (validator != null) {336                        if (optional && (actual.isNotPresent() || actual.isNull())) {337                            // pass338                        } else if (!optional && actual.isNotPresent()) {339                            // if the element is not present the expected result can only be340                            // the notpresent keyword, ignored or an optional comparison341                            return expected.isNotPresent() || "#ignore".contentEquals(expected.getAsString());342                        } else {343                            Match.Result mr = validator.apply(actual);344                            if (!mr.pass) {345                                return fail(mr.message);346                            }347                        }348                    } else if (!validatorName.startsWith(REGEX)) { // expected is a string that happens to start with "#"349                        String actualValue = actual.getValue();350                        switch (type) {351                            case CONTAINS:352                                return actualValue.contains(expStr);353                            default:354                                return actualValue.equals(expStr);355                        }356                    }357                }358                macro = StringUtils.trimToNull(macro);359                if (macro != null && questionPos != -1) {360                    context.JS.put("$", context.root.actual.getValue());361                    context.JS.put("_", actual.getValue());362                    JsValue jv = context.JS.eval(macro);363                    context.JS.bindings.removeMember("$");364                    context.JS.bindings.removeMember("_");365                    if (!jv.isTrue()) {366                        return fail("evaluated to 'false'");367                    }368                }369            }370        }371        return true; // all ok372    }373    private boolean actualEqualsExpected() {374        switch (actual.type) {375            case NULL:376                return true; // both are null377            case BOOLEAN:378                boolean actBoolean = actual.getValue();379                boolean expBoolean = expected.getValue();380                return actBoolean == expBoolean;381            case NUMBER:382                if (actual.getValue() instanceof BigDecimal || expected.getValue() instanceof BigDecimal) {383                    BigDecimal actBigDecimal = toBigDecimal(actual.getValue());384                    BigDecimal expBigDecimal = toBigDecimal(expected.getValue());385                    return actBigDecimal.compareTo(expBigDecimal) == 0;386                } else {387                    Number actNumber = actual.getValue();388                    Number expNumber = expected.getValue();389                    return actNumber.doubleValue() == expNumber.doubleValue();390                }391            case STRING:392                return actual.getValue().equals(expected.getValue());393            case BYTES:394                byte[] actBytes = actual.getValue();395                byte[] expBytes = expected.getValue();396                return Arrays.equals(actBytes, expBytes);397            case LIST:398                List actList = actual.getValue();399                List expList = expected.getValue();400                int actListCount = actList.size();401                int expListCount = expList.size();402                if (actListCount != expListCount) {403                    return fail("actual array length is not equal to expected - " + actListCount + ":" + expListCount);404                }405                for (int i = 0; i < actListCount; i++) {406                    Match.Value actListValue = new Match.Value(actList.get(i));407                    Match.Value expListValue = new Match.Value(expList.get(i));408                    MatchOperation mo = new MatchOperation(context.descend(i), Match.Type.EQUALS, actListValue, expListValue);409                    mo.execute();410                    if (!mo.pass) {411                        return fail("array match failed at index " + i);412                    }413                }414                return true;415            case MAP:416                Map<String, Object> actMap = actual.getValue();417                Map<String, Object> expMap = expected.getValue();418                return matchMapValues(actMap, expMap);419            case XML:420                Map<String, Object> actXml = (Map) XmlUtils.toObject(actual.getValue(), true);421                Map<String, Object> expXml = (Map) XmlUtils.toObject(expected.getValue(), true);422                return matchMapValues(actXml, expXml);423            case OTHER:424                return actual.getValue().equals(expected.getValue());425            default:426                throw new RuntimeException("unexpected type (match equals): " + actual.type);427        }428    }429    private boolean matchMapValues(Map<String, Object> actMap, Map<String, Object> expMap) { // combined logic for equals and contains430        if (actMap.size() > expMap.size() && (type == Match.Type.EQUALS || type == Match.Type.CONTAINS_ONLY)) {431            int sizeDiff = actMap.size() - expMap.size();432            Map<String, Object> diffMap = new LinkedHashMap(actMap);433            for (String key : expMap.keySet()) {434                diffMap.remove(key);435            }436            return fail("actual has " + sizeDiff + " more key(s) than expected - " + JsonUtils.toJson(diffMap));437        }438        Set<String> unMatchedKeysAct = new LinkedHashSet(actMap.keySet());439        Set<String> unMatchedKeysExp = new LinkedHashSet(expMap.keySet());440        for (Map.Entry<String, Object> expEntry : expMap.entrySet()) {441            String key = expEntry.getKey();442            Object childExp = expEntry.getValue();443            if (!actMap.containsKey(key)) {444                if (childExp instanceof String) {445                    String childString = (String) childExp;446                    if (childString.startsWith("##") || childString.equals("#ignore") || childString.equals("#notpresent")) {447                        if (type == Match.Type.CONTAINS_ANY || type == Match.Type.CONTAINS_ANY_DEEP) {448                            return true; // exit early449                        }450                        unMatchedKeysExp.remove(key);451                        if (unMatchedKeysExp.isEmpty()) {452                            if (type == Match.Type.CONTAINS || type == Match.Type.CONTAINS_DEEP) {453                                return true; // all expected keys matched454                            }455                        }456                        continue;457                    }458                }459                if (type != Match.Type.CONTAINS_ANY && type != Match.Type.CONTAINS_ANY_DEEP) {460                    return fail("actual does not contain key - '" + key + "'");461                }462            }463            Match.Value childActValue = new Match.Value(actMap.get(key));464            Match.Type childMatchType;465            if (type == Match.Type.CONTAINS_DEEP) {466                childMatchType = childActValue.isMapOrListOrXml() ? Match.Type.CONTAINS_DEEP : Match.Type.EQUALS;467            } else {468                childMatchType = Match.Type.EQUALS;469            }470            MatchOperation mo = new MatchOperation(context.descend(key), childMatchType, childActValue, new Match.Value(childExp));471            mo.execute();472            if (mo.pass) {473                if (type == Match.Type.CONTAINS_ANY || type == Match.Type.CONTAINS_ANY_DEEP) {474                    return true; // exit early475                }476                unMatchedKeysExp.remove(key);477                if (unMatchedKeysExp.isEmpty()) {478                    if (type == Match.Type.CONTAINS || type == Match.Type.CONTAINS_DEEP) {479                        return true; // all expected keys matched480                    }481                }482                unMatchedKeysAct.remove(key);483            } else if (type == Match.Type.EQUALS) {484                return fail("match failed for name: '" + key + "'");485            }486        }487        if (type == Match.Type.CONTAINS_ANY || type == Match.Type.CONTAINS_ANY_DEEP) {488            return unMatchedKeysExp.isEmpty() ? true : fail("no key-values matched");489        }490        if (unMatchedKeysExp.isEmpty()) { 491            if (type == Match.Type.CONTAINS || type == Match.Type.CONTAINS_DEEP) {492                return true; // all expected keys matched, expMap was empty in the first place    493            }494            if (type == Match.Type.NOT_CONTAINS && !expMap.isEmpty()) {495                return true; // hack alert: the NOT_CONTAINS will be reversed by the calling routine496            }497        }498        if (!unMatchedKeysExp.isEmpty()) {499            return fail("all key-values did not match, expected has un-matched keys - " + unMatchedKeysExp);500        }501        if (!unMatchedKeysAct.isEmpty()) {502            return fail("all key-values did not match, actual has un-matched keys - " + unMatchedKeysAct);503        }504        return true;505    }506    private boolean actualContainsExpected() {507        switch (actual.type) {508            case STRING:509                String actString = actual.getValue();510                String expString = expected.getValue();511                return actString.contains(expString);512            case LIST:513                List actList = actual.getValue();514                List expList = expected.getValue();515                int actListCount = actList.size();516                int expListCount = expList.size();517                if (type != Match.Type.CONTAINS_ANY && type != Match.Type.CONTAINS_ANY_DEEP && expListCount > actListCount) {518                    return fail("actual array length is less than expected - " + actListCount + ":" + expListCount);519                }520                if (type == Match.Type.CONTAINS_ONLY && expListCount != actListCount) {521                    return fail("actual array length is not equal to expected - " + actListCount + ":" + expListCount);522                }523                for (Object exp : expList) { // for each item in the expected list524                    boolean found = false;525                    Match.Value expListValue = new Match.Value(exp);526                    for (int i = 0; i < actListCount; i++) {527                        Match.Value actListValue = new Match.Value(actList.get(i));528                        Match.Type childMatchType;529                        switch (type) {530                            case CONTAINS_DEEP:531                                childMatchType = actListValue.isMapOrListOrXml() ? Match.Type.CONTAINS_DEEP : Match.Type.EQUALS;532                                break;533                            case CONTAINS_ANY_DEEP:534                                childMatchType = actListValue.isMapOrListOrXml() ? Match.Type.CONTAINS_ANY : Match.Type.EQUALS;535                                break;536                            default:537                                childMatchType = Match.Type.EQUALS;538                        }539                        MatchOperation mo = new MatchOperation(context.descend(i), childMatchType, actListValue, expListValue);540                        mo.execute();541                        if (mo.pass) {542                            if (type == Match.Type.CONTAINS_ANY || type == Match.Type.CONTAINS_ANY_DEEP) {543                                return true; // exit early544                            } else {545                                found = true;546                                break; // next item in expected list547                            }548                        }549                    }550                    if (!found && type != Match.Type.CONTAINS_ANY && type != Match.Type.CONTAINS_ANY_DEEP) { // if we reached here, all items in the actual list were scanned551                        return fail("actual array does not contain expected item - " + expListValue.getAsString());552                    }553                }554                if (type == Match.Type.CONTAINS_ANY || type == Match.Type.CONTAINS_ANY_DEEP) {555                    return fail("actual array does not contain any of the expected items");556                }557                return true; // if we reached here, all items in the expected list were found558            case MAP:559                Map<String, Object> actMap = actual.getValue();560                Map<String, Object> expMap = expected.getValue();561                return matchMapValues(actMap, expMap);562            case XML:563                Map<String, Object> actXml = (Map) XmlUtils.toObject(actual.getValue());564                Map<String, Object> expXml = (Map) XmlUtils.toObject(expected.getValue());565                return matchMapValues(actXml, expXml);566            default:567                throw new RuntimeException("unexpected type (match contains): " + actual.type);568        }569    }570    private static BigDecimal toBigDecimal(Object o) {571        if (o instanceof BigDecimal) {572            return (BigDecimal) o;573        } else if (o instanceof Number) {574            Number n = (Number) o;575            return BigDecimal.valueOf(n.doubleValue());576        } else {577            throw new RuntimeException("expected number instead of: " + o);578        }579    }580    private boolean pass() {581        pass = true;582        return true;583    }584    private boolean fail(String reason) {585        pass = false;586        if (reason == null) {587            return false;588        }589        failReason = failReason == null ? reason : reason + " | " + failReason;590        context.root.failures.add(this);591        return false;592    }593    String getFailureReasons() {594        return collectFailureReasons(this);595    }596    private boolean isXmlAttributeOrMap() {597        return context.xml && actual.isMap()598                && (context.name.equals("@") || actual.<Map>getValue().containsKey("_"));599    }600    private static String collectFailureReasons(MatchOperation root) {601        StringBuilder sb = new StringBuilder();602        sb.append("match failed: ").append(root.type).append('\n');603        Collections.reverse(root.failures);604        Iterator<MatchOperation> iterator = root.failures.iterator();605        Set previousPaths = new HashSet();606        int index = 0;607        int prevDepth = -1;608        while (iterator.hasNext()) {609            MatchOperation mo = iterator.next();610            if (previousPaths.contains(mo.context.path) || mo.isXmlAttributeOrMap()) {611                continue;612            }613            previousPaths.add(mo.context.path);614            if (mo.context.depth != prevDepth) {615                prevDepth = mo.context.depth;616                index++;617            }618            String prefix = StringUtils.repeat(' ', index * 2);619            sb.append(prefix).append(mo.context.path).append(" | ").append(mo.failReason);620            sb.append(" (").append(mo.actual.type).append(':').append(mo.expected.type).append(")");621            sb.append('\n');622            if (mo.context.xml) {623                sb.append(prefix).append(mo.actual.getAsXmlString()).append('\n');...Source:Match.java  
...145    146    static class Context {147        148        final JsEngine JS;149        final MatchOperation root;150        final int depth;151        final boolean xml;152        final String path;153        final String name;154        final int index;155        156        Context(JsEngine js, MatchOperation root, boolean xml, int depth, String path, String name, int index) {157            this.JS = js;158            this.root = root;159            this.xml = xml;160            this.depth = depth;161            this.path = path;162            this.name = name;163            this.index = index;164        }165        166        Context descend(String name) {167            if (xml) {168                String childPath = path.endsWith("/@") ? path + name : (depth == 0 ? "" : path) + "/" + name;169                return new Context(JS, root, xml, depth + 1, childPath, name, -1);170            } else {171                boolean needsQuotes = name.indexOf('-') != -1 || name.indexOf(' ') != -1 || name.indexOf('.') != -1;172                String childPath = needsQuotes ? path + "['" + name + "']" : path + '.' + name;173                return new Context(JS, root, xml, depth + 1, childPath, name, -1);174            }175        }176        177        Context descend(int index) {178            if (xml) {179                return new Context(JS, root, xml, depth + 1, path + "[" + (index + 1) + "]", name, index);180            } else {181                return new Context(JS, root, xml, depth + 1, path + "[" + index + "]", name, index);182            }183        }184        185    }186    187    static enum ValueType {188        NULL,189        BOOLEAN,190        NUMBER,191        STRING,192        BYTES,193        LIST,194        MAP,195        XML,196        OTHER197    }198    199    public static class Value {200        201        final ValueType type;202        final boolean exceptionOnMatchFailure;203        204        private final Object value;205        206        Value(Object value) {207            this(value, false);208        }209        210        Value(Object value, boolean exceptionOnMatchFailure) {211            if (value instanceof Set) {212                value = new ArrayList((Set) value);213            } else if (value != null && value.getClass().isArray()) {                214                int length = Array.getLength(value);215                List list = new ArrayList(length);216                for (int i = 0; i < length; i++) {217                    list.add(Array.get(value, i));218                }219                value = list;220            }221            this.value = value;222            this.exceptionOnMatchFailure = exceptionOnMatchFailure;223            if (value == null) {224                type = ValueType.NULL;225            } else if (value instanceof Node) {226                type = ValueType.XML;227            } else if (value instanceof List) {228                type = ValueType.LIST;229            } else if (value instanceof Map) {230                type = ValueType.MAP;231            } else if (value instanceof String) {232                type = ValueType.STRING;233            } else if (Number.class.isAssignableFrom(value.getClass())) {234                type = ValueType.NUMBER;235            } else if (Boolean.class.equals(value.getClass())) {236                type = ValueType.BOOLEAN;237            } else if (value instanceof byte[]) {238                type = ValueType.BYTES;239            } else {240                type = ValueType.OTHER;241            }242        }243        244        public boolean isBoolean() {245            return type == ValueType.BOOLEAN;246        }247        248        public boolean isNumber() {249            return type == ValueType.NUMBER;250        }251        252        public boolean isString() {253            return type == ValueType.STRING;254        }255        256        public boolean isNull() {257            return type == ValueType.NULL;258        }259        260        public boolean isMap() {261            return type == ValueType.MAP;262        }263        264        public boolean isList() {265            return type == ValueType.LIST;266        }267        268        public boolean isXml() {269            return type == ValueType.XML;270        }271        272        boolean isNotPresent() {273            return "#notpresent".equals(value);274        }275        276        boolean isMapOrListOrXml() {277            switch (type) {278                case MAP:279                case LIST:280                case XML:281                    return true;282                default:283                    return false;284            }285        }286        287        public <T> T getValue() {288            return (T) value;289        }290        291        String getWithinSingleQuotesIfString() {292            if (type == ValueType.STRING) {293                return "'" + value + "'";294            } else {295                return getAsString();296            }297        }298        299        public String getAsString() {300            switch (type) {301                case LIST:302                case MAP:303                    return JsonUtils.toJsonSafe(value, false);304                case XML:305                    return XmlUtils.toString(getValue());306                default:307                    return value + "";308            }309        }310        311        String getAsXmlString() {312            if (type == ValueType.MAP) {313                Node node = XmlUtils.fromMap(getValue());314                return XmlUtils.toString(node);315            } else {316                return getAsString();317            }318        }319        320        Value getSortedLike(Value other) {321            if (isMap() && other.isMap()) {322                Map<String, Object> reference = other.getValue();323                Map<String, Object> source = getValue();324                Set<String> remainder = new LinkedHashSet(source.keySet());325                Map<String, Object> result = new LinkedHashMap(source.size());326                reference.keySet().forEach(key -> {327                    if (source.containsKey(key)) {328                        result.put(key, source.get(key));329                        remainder.remove(key);330                    }331                });332                for (String key : remainder) {333                    result.put(key, source.get(key));334                }335                return new Value(result, other.exceptionOnMatchFailure);336            } else {337                return this;338            }339        }340        341        @Override342        public String toString() {343            StringBuilder sb = new StringBuilder();344            sb.append("[type: ").append(type);345            sb.append(", value: ").append(value);346            sb.append("]");347            return sb.toString();348        }349        350        public Result is(Type matchType, Object expected) {351            MatchOperation mo = new MatchOperation(matchType, this, new Value(parseIfJsonOrXmlString(expected), exceptionOnMatchFailure));352            mo.execute();353            if (mo.pass) {354                return Match.PASS;355            } else {356                if (exceptionOnMatchFailure) {357                    throw new RuntimeException(mo.getFailureReasons());358                }359                return Match.fail(mo.getFailureReasons());360            }361        }362        //======================================================================363        //364        public Result isEqualTo(Object expected) {365            return is(Type.EQUALS, expected);366        }367        368        public Result contains(Object expected) {369            return is(Type.CONTAINS, expected);370        }371        372        public Result containsDeep(Object expected) {373            return is(Type.CONTAINS_DEEP, expected);374        }375        376        public Result containsOnly(Object expected) {377            return is(Type.CONTAINS_ONLY, expected);378        }379        380        public Result containsAny(Object expected) {381            return is(Type.CONTAINS_ANY, expected);382        }383        384        public Result isNotEqualTo(Object expected) {385            return is(Type.NOT_EQUALS, expected);386        }387        388        public Result isNotContaining(Object expected) {389            return is(Type.NOT_CONTAINS, expected);390        }391        392        public Result isEachEqualTo(Object expected) {393            return is(Type.EACH_EQUALS, expected);394        }395        396        public Result isEachNotEqualTo(Object expected) {397            return is(Type.EACH_NOT_EQUALS, expected);398        }399        400        public Result isEachContaining(Object expected) {401            return is(Type.EACH_CONTAINS, expected);402        }403        404        public Result isEachNotContaining(Object expected) {405            return is(Type.EACH_NOT_CONTAINS, expected);406        }407        408        public Result isEachContainingDeep(Object expected) {409            return is(Type.EACH_CONTAINS_DEEP, expected);410        }411        412        public Result isEachContainingOnly(Object expected) {413            return is(Type.EACH_CONTAINS_ONLY, expected);414        }415        416        public Result isEachContainingAny(Object expected) {417            return is(Type.EACH_CONTAINS_ANY, expected);418        }419        420    }421    422    public static Result execute(JsEngine js, Type matchType, Object actual, Object expected) {423        MatchOperation mo = new MatchOperation(js, matchType, new Value(actual), new Value(expected));424        mo.execute();425        if (mo.pass) {426            return PASS;427        } else {428            return fail(mo.getFailureReasons());429        }430    }431    432    public static Object parseIfJsonOrXmlString(Object o) {433        if (o instanceof String) {434            String s = (String) o;435            if (s.isEmpty()) {436                return o;437            } else if (JsonUtils.isJson(s)) {...MatchOperation
Using AI Code Generation
1import com.intuit.karate.MatchOperation;2import com.intuit.karate.Match;3import com.intuit.karate.MatchType;4import com.intuit.karate.MatchMode;5public class MatchOperationExample {6    public static void main(String[] args) {7        MatchOperation matchOperation = new MatchOperation();8        Match match = new Match();9        match.setMatchType(MatchType.EQUALS);10        match.setMatchMode(MatchMode.STRICT);11        match.setMatchValue("test");12        matchOperation.setMatch(match);13        matchOperation.setOperation("test");14        matchOperation.setOperationType("test");15        matchOperation.setOperationValue("test");16        matchOperation.setOperation("test");17        matchOperation.setOperationType("test");18        matchOperation.setOperationValue("test");19        matchOperation.setOperation("test");20        matchOperation.setOperationType("test");21        matchOperation.setOperationValue("test");22        matchOperation.setOperation("test");23        matchOperation.setOperationType("test");24        matchOperation.setOperationValue("test");25        matchOperation.setOperation("test");26        matchOperation.setOperationType("test");27        matchOperation.setOperationValue("test");28        matchOperation.setOperation("test");29        matchOperation.setOperationType("testMatchOperation
Using AI Code Generation
1import com.intuit.karate.MatchOperation;2import com.intuit.karate.MatchType;3import com.intuit.karate.MatchOptions;4import com.intuit.karate.Match;5import com.intuit.karate.MatchResult;6import com.intuit.karate.MatchUtils;7import com.intuit.karate.FileUtils;8import java.util.List;9import java.util.Map;10public class 4 {11    public static void main(String[] args) {12        String exp = FileUtils.toString(args[0]);13        String act = FileUtils.toString(args[1]);14        MatchOptions options = new MatchOptions();15        options.setIgnoreArrayOrder(true);16        options.setIgnoreExtraElements(true);17        Match match = new Match(exp, act, options);18        List<MatchResult> results = match.match();19        System.out.println(MatchUtils.getSummary(results));20        System.out.println(MatchUtils.getDetails(results));21    }22}23import com.intuit.karate.MatchOperation;24import com.intuit.karate.MatchType;25import com.intuit.karate.MatchOptions;26import com.intuit.karate.Match;27import com.intuit.karate.MatchResult;28import com.intuit.karate.MatchUtils;29import com.intuit.karate.FileUtils;30import java.util.List;31import java.util.Map;32public class 5 {33    public static void main(String[] args) {34        String exp = FileUtils.toString(args[0]);35        String act = FileUtils.toString(args[1]);36        MatchOptions options = new MatchOptions();37        options.setIgnoreArrayOrder(true);38        options.setIgnoreExtraElements(true);39        Match match = new Match(exp, act, options);40        List<MatchResult> results = match.match();41        System.out.println(MatchUtils.getSummary(results));42        System.out.println(MatchUtils.getDetails(results));43    }44}45import com.intuit.karate.MatchOperation;46import com.intuit.karate.MatchType;47import com.intuit.karate.MatchOptions;48import com.intuit.karate.Match;49import com.intuit.karate.MatchResult;50import com.intuit.karate.MatchUtils;51import com.intuit.karate.FileUtils;52import java.util.List;53import java.util.MapMatchOperation
Using AI Code Generation
1import com.intuit.karate.MatchOperation;2import com.intuit.karate.MatchType;3import com.intuit.karate.MatchOptions;4MatchOptions options = new MatchOptions();5options.setMatchType(MatchType.STRICT);6options.setAllowExtraNulls(true);7options.setAllowExtraElements(true);8options.setAllowExtraAttributes(true);9options.setAllowExtraText(true);10options.setAllowExtraRoot(true);11options.setAllowMissingRoot(true);12options.setAllowMissingAttributes(true);13options.setAllowMissingElements(true);14options.setAllowMissingNulls(true);15options.setAllowMissingText(true);16options.setAllowExtraRoot(true);17options.setAllowUnexpectedKeys(true);18options.setAllowUnexpectedValues(true);19options.setAllowMissingKeys(true);20options.setAllowMissingValues(true);21options.setAllowNullKeys(true);22options.setAllowNullValues(true);23options.setAllowDuplicateKeys(true);24options.setAllowDuplicateValues(true);25options.setAllowEmptyValues(true);26options.setAllowEmptyStrings(true);27options.setAllowEmptyArrays(true);28options.setAllowEmptyObjects(true);29options.setAllowEmptyRoot(true);30MatchOperation match = new MatchOperation(options);31boolean result = match.match(actual, expected);32import com.intuit.karate.Match;33import com.intuit.karate.MatchType;34import com.intuit.karate.MatchOptions;35MatchOptions options = new MatchOptions();36options.setMatchType(MatchType.STRICT);37options.setAllowExtraNulls(true);38options.setAllowExtraElements(true);39options.setAllowExtraAttributes(true);40options.setAllowExtraText(true);41options.setAllowExtraRoot(true);42options.setAllowMissingRoot(true);43options.setAllowMissingAttributes(true);44options.setAllowMissingElements(true);45options.setAllowMissingNulls(true);46options.setAllowMissingText(true);47options.setAllowExtraRoot(true);48options.setAllowUnexpectedKeys(true);49options.setAllowUnexpectedValues(true);50options.setAllowMissingKeys(true);51options.setAllowMissingValues(true);52options.setAllowNullKeys(true);53options.setAllowNullValues(true);54options.setAllowDuplicateKeys(true);55options.setAllowDuplicateValues(true);56options.setAllowEmptyValues(true);57options.setAllowEmptyStrings(true);58options.setAllowEmptyArrays(true);59options.setAllowEmptyObjects(true);60options.setAllowEmptyRoot(true);61Match match = new Match(actual, expected, options);62boolean result = match.match();MatchOperation
Using AI Code Generation
1package demo;2public class 4 {3    public static void main(String[] args) {4        String str1 = "This is a string";5        String str2 = "This is a string";6        MatchOperation matchOp = new MatchOperation(str1, str2, MatchType.EQUALS);7    }8}9Java String split() Method10Java String join() Method11Java String format() Method12Java String substring() Method13Java String strip() Method14Java String replace() Method15Java String replaceAll() Method16Java String replaceFirst() Method17Java String toLowerCase() Method18Java String toUpperCase() Method19Java String trim() Method20Java String isBlank() Method21Java String isEmpty() MethodMatchOperation
Using AI Code Generation
1import com.intuit.karate.MatchOperation;2import com.intuit.karate.MatchType;3import com.intuit.karate.MatchOptions;4import com.intuit.karate.Match;5MatchOptions options = MatchOptions.builder()6    .matchType(MatchType.STRICT)7    .build();8MatchOperation operation = MatchOperation.builder()9    .options(options)10    .build();11Match match = operation.match(actual, expected);12boolean isMatch = match.isMatch();13System.out.println("isMatch = " + isMatch);14import com.intuit.karate.MatchOperation;15import com.intuit.karate.MatchType;16import com.intuit.karate.MatchOptions;17import com.intuit.karate.Match;18MatchOptions options = MatchOptions.builder()19    .matchType(MatchType.STRICT)20    .build();21MatchOperation operation = MatchOperation.builder()22    .options(options)23    .build();24Match match = operation.match(actual, expected);25boolean isMatch = match.isMatch();26System.out.println("isMatch = " + isMatch);27import com.intuit.karate.MatchOperation;28import com.intuit.karate.MatchType;29import com.intuit.karate.MatchOptions;30import com.intuit.karate.Match;31MatchOptions options = MatchOptions.builder()32    .matchType(MatchType.STRICT)33    .build();34MatchOperation operation = MatchOperation.builder()35    .options(options)36    .build();37Match match = operation.match(actual, expected);38boolean isMatch = match.isMatch();39System.out.println("isMatch = " + isMatch);40import com.intuit.karate.MatchOperation;41import com.intuit.karate.MatchType;42import com.intuit.karate.MatchOptions;43import com.intuit.karate.Match;44MatchOptions options = MatchOptions.builder()45    .matchType(MatchType.STRICT)46    .build();47MatchOperation operation = MatchOperation.builder()48    .options(options)49    .build();50Match match = operation.match(actual, expected);51boolean isMatch = match.isMatch();52System.out.println("isMatch = " + isMatch);MatchOperation
Using AI Code Generation
1package com.intuit.karate;2import org.junit.Test;3import com.intuit.karate.junit5.Karate;4public class TestRunner {5  public void testParallel() {6    Karate.run().tags("@test").relativeTo(getClass());7  }8}9    And match response == { "name" : "John", "age" : 30, "car" : null }10{11}12package com.intuit.karate;13import org.junit.Test;14import com.intuit.karate.junit5.Karate;15public class TestRunner {16  public void testParallel() {17    Karate.run().tags("@test").relativeTo(getClass());18  }19}20    And match response == { "name" : "John", "age" : 30, "car" : null }21{22}MatchOperation
Using AI Code Generation
1package com.intuit.karate.demo;2import com.intuit.karate.Match;3import com.intuit.karate.MatchType;4import com.intuit.karate.MatchUtils;5import com.intuit.karate.core.ScenarioContext;6import com.intuit.karate.core.Variable;7import com.intuit.karate.core.VariableScope;8import com.intuit.karate.http.HttpResponse;9import com.intuit.karate.http.HttpUtils;10import com.intuit.karate.http.MultiValuedTreeMap;11import com.intuit.karate.http.MultiValuedTreeMapImpl;12import com.intuit.karate.http.Request;13import com.intuit.karate.http.Response;14import com.intuit.karate.http.ResponseOptions;15import com.intuit.karate.http.ResponseWrapper;16import com.intuit.karate.http.Session;17import com.intuit.karate.http.SessionOptions;18import com.intuit.karate.http.SessionWrapper;19import com.intuit.karate.http.WebSocket;20import com.intuit.karate.http.WebSocketOptions;21import com.intuit.karate.http.WebSocketWrapper;22import com.intuit.karate.http.Cookie;23import com.intuit.karate.http.CookieOptions;24import com.intuit.karate.http.CookieWrapper;25import com.intuit.karate.http.MultiValuedMap;26import com.intuit.karate.http.HttpClient;27import com.intuit.karate.http.HttpClientOptions;28import com.intuit.karate.http.HttpClientWrapper;29import com.intuit.karate.http.HttpClientFactory;30import com.intuit.karate.http.HttpClientFactoryOptions;31import com.intuit.karate.http.HttpClientFactoryWrapper;32import com.intuit.karate.http.HttpClientFactoryOptionsWrapper;33import com.intuit.karate.http.HttpClientOptionsWrapper;34import com.intuit.karate.http.HttpClientWrapper;35import com.intuit.karate.http.Cookie;36import com.intuit.karate.http.CookieOptions;37import com.intuit.karate.http.CookieWrapper;38import com.intuit.karate.http.MultiValuedMap;39import com.intuit.karate.http.HttpClient;40import com.intuit.karate.http.HttpClientOptions;41import com.intuit.karate.http.HttpClientWrapper;42import com.intuit.kLearn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
