A collection of Validation Errors returned by the Braintree Gateway
 public void Size_WithShallowErrors()
 {
     ValidationErrors errors = new ValidationErrors();
     errors.AddError("country_name", new ValidationError("country_name", "1", "invalid country"));
     errors.AddError("another_field", new ValidationError("another_field", "2", "another message"));
     Assert.AreEqual(2, errors.Count);
 }
 public void OnField_WithValidationError()
 {
     ValidationErrors errors = new ValidationErrors();
     errors.AddError("country_name", new ValidationError("country_name", "91803", "invalid country"));
     Assert.AreEqual(ValidationErrorCode.ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED, errors.OnField("country_name")[0].Code);
     Assert.AreEqual("invalid country", errors.OnField("country_name")[0].Message);
 }
        public void ForObject_WithNestedErrors()
        {
            ValidationErrors addressErrors = new ValidationErrors();
            addressErrors.AddError("country_name", new ValidationError("country_name", "91803", "invalid country"));

            ValidationErrors errors = new ValidationErrors();
            errors.AddErrors("address", addressErrors);
            Assert.AreEqual(ValidationErrorCode.ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED, errors.ForObject("address").OnField("country_name")[0].Code);
            Assert.AreEqual("invalid country", errors.ForObject("address").OnField("country_name")[0].Message);
        }
 public void ForObject_WorksWithAllCommonCasing()
 {
     ValidationErrors nestedErrors = new ValidationErrors();
     ValidationErrors errors = new ValidationErrors();
     errors.AddErrors("credit-card", nestedErrors);
     Assert.AreEqual(nestedErrors, errors.ForObject("credit-card"));
     Assert.AreEqual(nestedErrors, errors.ForObject("credit_card"));
     Assert.AreEqual(nestedErrors, errors.ForObject("creditCard"));
     Assert.AreEqual(nestedErrors, errors.ForObject("CreditCard"));
 }
 public void OnField_WorksWithAllCommonCasing()
 {
     ValidationError fieldError = new ValidationError("", "1", "");
     ValidationErrors errors = new ValidationErrors();
     errors.AddError("country_name", fieldError);
     Assert.AreEqual(fieldError, errors.OnField("country_name")[0]);
     Assert.AreEqual(fieldError, errors.OnField("country-name")[0]);
     Assert.AreEqual(fieldError, errors.OnField("countryName")[0]);
     Assert.AreEqual(fieldError, errors.OnField("CountryName")[0]);
 }
예제 #6
0
        public void DeepCount_WithNestedErrors()
        {
            ValidationErrors addressErrors = new ValidationErrors();
            addressErrors.AddError("country_name", new ValidationError("country_name", "1", "invalid country"));
            addressErrors.AddError("another_field", new ValidationError("another_field", "2", "another message"));

            ValidationErrors errors = new ValidationErrors();
            errors.AddError("some_field", new ValidationError("some_field", "3", "some message"));
            errors.AddErrors("address", addressErrors);

            Assert.AreEqual(3, errors.DeepCount);
            Assert.AreEqual(1, errors.Count);

            Assert.AreEqual(2, errors.ForObject("address").DeepCount);
            Assert.AreEqual(2, errors.ForObject("address").Count);
        }
        public void DeepAll_ReturnsValidationErrorsAtEveryLevel()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            builder.Append("<api-error-response>");
            builder.Append("  <errors>");
            builder.Append("    <customer>");
            builder.Append("      <errors type=\"array\">");
            builder.Append("        <error>");
            builder.Append("          <code>81608</code>");
            builder.Append("          <message>First name is too long.</message>");
            builder.Append("          <attribute type=\"symbol\">first_name</attribute>");
            builder.Append("        </error>");
            builder.Append("      </errors>");
            builder.Append("      <credit-card>");
            builder.Append("        <errors type=\"array\">");
            builder.Append("          <error>");
            builder.Append("            <code>81715</code>");
            builder.Append("            <message>Credit card number is invalid.</message>");
            builder.Append("            <attribute type=\"symbol\">number</attribute>");
            builder.Append("          </error>");
            builder.Append("          <error>");
            builder.Append("            <code>81710</code>");
            builder.Append("            <message>Expiration date is invalid.</message>");
            builder.Append("            <attribute type=\"symbol\">expiration_date</attribute>");
            builder.Append("          </error>");
            builder.Append("        </errors>");
            builder.Append("      </credit-card>");
            builder.Append("    </customer>");
            builder.Append("    <errors type=\"array\"/>");
            builder.Append("  </errors>");
            builder.Append("</api-error-response>");

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(builder.ToString());
            ValidationErrors errors = new ValidationErrors(new NodeWrapper(doc.ChildNodes[1]));

            Assert.AreEqual(3, errors.DeepAll().Count);

            Assert.AreEqual("first_name", errors.DeepAll()[0].Attribute);
            Assert.AreEqual(ValidationErrorCode.CUSTOMER_FIRST_NAME_IS_TOO_LONG, errors.DeepAll()[0].Code);

            Assert.AreEqual("number", errors.DeepAll()[1].Attribute);
            Assert.AreEqual(ValidationErrorCode.CREDIT_CARD_NUMBER_IS_INVALID, errors.DeepAll()[1].Code);

            Assert.AreEqual("expiration_date", errors.DeepAll()[2].Attribute);
            Assert.AreEqual(ValidationErrorCode.CREDIT_CARD_EXPIRATION_DATE_IS_INVALID, errors.DeepAll()[2].Code);


            Assert.AreEqual(3, errors.ForObject("customer").DeepAll().Count);

            Assert.AreEqual("first_name", errors.ForObject("customer").DeepAll()[0].Attribute);
            Assert.AreEqual(ValidationErrorCode.CUSTOMER_FIRST_NAME_IS_TOO_LONG, errors.ForObject("customer").DeepAll()[0].Code);

            Assert.AreEqual("number", errors.ForObject("customer").DeepAll()[1].Attribute);
            Assert.AreEqual(ValidationErrorCode.CREDIT_CARD_NUMBER_IS_INVALID, errors.ForObject("customer").DeepAll()[1].Code);

            Assert.AreEqual("expiration_date", errors.ForObject("customer").DeepAll()[2].Attribute);
            Assert.AreEqual(ValidationErrorCode.CREDIT_CARD_EXPIRATION_DATE_IS_INVALID, errors.ForObject("customer").DeepAll()[2].Code);
        }
 public void OnField_WithNonExistingField()
 {
     ValidationErrors errors = new ValidationErrors();
     Assert.IsNull(errors.OnField("foo"));
 }
        public void ByFormField_UnderscoresNodes()
        {
            var errors = new ValidationErrors();
            errors.AddError("some-error", new ValidationError("some-error", "1", "some error"));
            errors.AddError("some-error", new ValidationError("some-error", "2", "some other error"));

            var nestedErrors = new ValidationErrors();
            nestedErrors.AddError("some-nested-error", new ValidationError("some-nested-error", "3", "some nested error"));
            nestedErrors.AddError("some-nested-error", new ValidationError("some-nested-error", "4", "some other nested error"));

            var nestedNestedErrors = new ValidationErrors();
            nestedNestedErrors.AddError("some-nested-nested-error", new ValidationError("some-nested-nested-error", "5", "some nested nested error"));
            nestedNestedErrors.AddError("some-nested-nested-error", new ValidationError("some-nested-nested-error", "6", "some other nested nested error"));

            nestedErrors.AddErrors("some-nested-object", nestedNestedErrors);
            errors.AddErrors("some-object", nestedErrors);

            Dictionary<string, List<string>> formErrors = errors.ByFormField();
            Assert.AreEqual("some error", formErrors["some_error"][0]);
            Assert.AreEqual("some other error", formErrors["some_error"][1]);

            Assert.AreEqual("some nested error", formErrors["some_object[some_nested_error]"][0]);
            Assert.AreEqual("some other nested error", formErrors["some_object[some_nested_error]"][1]);

            Assert.AreEqual("some nested nested error", formErrors["some_object[some_nested_object][some_nested_nested_error]"][0]);
            Assert.AreEqual("some other nested nested error", formErrors["some_object[some_nested_object][some_nested_nested_error]"][1]);
        }
        public void Constructor_ParsesValidationErrorsAtMultipleLevels()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            builder.Append("<api-error-response>");
            builder.Append("  <errors>");
            builder.Append("    <customer>");
            builder.Append("      <errors type=\"array\">");
            builder.Append("        <error>");
            builder.Append("          <code>81608</code>");
            builder.Append("          <message>First name is too long.</message>");
            builder.Append("          <attribute type=\"symbol\">first_name</attribute>");
            builder.Append("        </error>");
            builder.Append("      </errors>");
            builder.Append("      <credit-card>");
            builder.Append("        <billing-address>");
            builder.Append("          <errors type=\"array\">");
            builder.Append("            <error>");
            builder.Append("              <code>91803</code>");
            builder.Append("              <message>Country name is not an accepted country.</message>");
            builder.Append("              <attribute type=\"symbol\">country_name</attribute>");
            builder.Append("            </error>");
            builder.Append("          </errors>");
            builder.Append("        </billing-address>");
            builder.Append("        <errors type=\"array\">");
            builder.Append("          <error>");
            builder.Append("            <code>81715</code>");
            builder.Append("            <message>Credit card number is invalid.</message>");
            builder.Append("            <attribute type=\"symbol\">number</attribute>");
            builder.Append("          </error>");
            builder.Append("        </errors>");
            builder.Append("      </credit-card>");
            builder.Append("    </customer>");
            builder.Append("    <errors type=\"array\"/>");
            builder.Append("  </errors>");
            builder.Append("</api-error-response>");

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(builder.ToString());
            ValidationErrors errors = new ValidationErrors(new NodeWrapper(doc.ChildNodes[1]));

            Assert.AreEqual(3, errors.DeepCount);
            Assert.AreEqual(0, errors.Count);

            Assert.AreEqual(3, errors.ForObject("customer").DeepCount);
            Assert.AreEqual(1, errors.ForObject("customer").Count);
            Assert.AreEqual(ValidationErrorCode.CUSTOMER_FIRST_NAME_IS_TOO_LONG, errors.ForObject("customer").OnField("first_name")[0].Code);

            Assert.AreEqual(2, errors.ForObject("customer").ForObject("credit-card").DeepCount);
            Assert.AreEqual(1, errors.ForObject("customer").ForObject("credit-card").Count);
            Assert.AreEqual(ValidationErrorCode.CREDIT_CARD_NUMBER_IS_INVALID, errors.ForObject("customer").ForObject("credit-card").OnField("number")[0].Code);

            Assert.AreEqual(1, errors.ForObject("customer").ForObject("credit-card").ForObject("billing-address").DeepCount);
            Assert.AreEqual(1, errors.ForObject("customer").ForObject("credit-card").ForObject("billing-address").Count);
            Assert.AreEqual(ValidationErrorCode.ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED, errors.ForObject("customer").ForObject("credit-card").ForObject("billing-address").OnField("country_name")[0].Code);
        }
예제 #11
0
        public void ByFormField_FlattensErrorsToFormElementNames()
        {
            var errors = new ValidationErrors();
            errors.AddError("some_error", new ValidationError("some_error", "1", "some error"));
            errors.AddError("some_error", new ValidationError("some_error", "2", "some other error"));

            var nestedErrors = new ValidationErrors();
            nestedErrors.AddError("some_nested_error", new ValidationError("some_nested_error", "3", "some nested error"));
            nestedErrors.AddError("some_nested_error", new ValidationError("some_nested_error", "4", "some other nested error"));

            var nestedNestedErrors = new ValidationErrors();
            nestedNestedErrors.AddError("some_nested_nested_error", new ValidationError("some_nested_nested_error", "5", "some nested nested error"));
            nestedNestedErrors.AddError("some_nested_nested_error", new ValidationError("some_nested_nested_error", "6", "some other nested nested error"));

            nestedErrors.AddErrors("some_nested_object", nestedNestedErrors);
            errors.AddErrors("some_object", nestedErrors);

            Dictionary<String, List<String>> formErrors = errors.ByFormField();
            Assert.AreEqual("some error", formErrors["some_error"][0]);
            Assert.AreEqual("some other error", formErrors["some_error"][1]);

            Assert.AreEqual("some nested error", formErrors["some_object[some_nested_error]"][0]);
            Assert.AreEqual("some other nested error", formErrors["some_object[some_nested_error]"][1]);

            Assert.AreEqual("some nested nested error", formErrors["some_object[some_nested_object][some_nested_nested_error]"][0]);
            Assert.AreEqual("some other nested nested error", formErrors["some_object[some_nested_object][some_nested_nested_error]"][1]);
        }
 public void ForObject_WithNonExistingObject()
 {
     ValidationErrors errors = new ValidationErrors();
     Assert.AreEqual(0, errors.ForObject("address").Count);
 }
        public void Constructor_ParsesMulitpleValidationErrorsOnOneObject()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            builder.Append("<api-error-response>");
            builder.Append("  <errors>");
            builder.Append("    <address>");
            builder.Append("      <errors type=\"array\">");
            builder.Append("        <error>");
            builder.Append("          <code>91803</code>");
            builder.Append("          <message>Country name is not an accepted country.</message>");
            builder.Append("          <attribute type=\"symbol\">country_name</attribute>");
            builder.Append("        </error>");
            builder.Append("        <error>");
            builder.Append("          <code>81812</code>");
            builder.Append("          <message>Street address is too long.</message>");
            builder.Append("          <attribute type=\"symbol\">street_address</attribute>");
            builder.Append("        </error>");
            builder.Append("      </errors>");
            builder.Append("    </address>");
            builder.Append("    <errors type=\"array\"/>");
            builder.Append("  </errors>");
            builder.Append("</api-error-response>");

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(builder.ToString());
            ValidationErrors errors = new ValidationErrors(new NodeWrapper(doc.ChildNodes[1]));
            Assert.AreEqual(2, errors.DeepCount);
            Assert.AreEqual(ValidationErrorCode.ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED, errors.ForObject("address").OnField("country_name")[0].Code);
            Assert.AreEqual(ValidationErrorCode.ADDRESS_STREET_ADDRESS_IS_TOO_LONG, errors.ForObject("address").OnField("street_address")[0].Code);
        }
        public WebhookNotification(NodeWrapper node, BraintreeGateway gateway)
        {
            Timestamp = node.GetDateTime("timestamp");
            Kind = (WebhookKind)CollectionUtil.Find(WebhookKind.ALL, node.GetString("kind"), WebhookKind.UNRECOGNIZED);

            NodeWrapper WrapperNode = node.GetNode("subject");

            if (WrapperNode.GetNode("api-error-response") != null) {
                WrapperNode = WrapperNode.GetNode("api-error-response");
            }

            if (WrapperNode.GetNode("subscription") != null) {
                Subscription = new Subscription(WrapperNode.GetNode("subscription"), gateway);
            }

            if (WrapperNode.GetNode("merchant-account") != null) {
                MerchantAccount = new MerchantAccount(WrapperNode.GetNode("merchant-account"));
            }

            if (WrapperNode.GetNode("dispute") != null) {
                Dispute = new Dispute(WrapperNode.GetNode("dispute"));
            }

            if (WrapperNode.GetNode("transaction") != null) {
                Transaction = new Transaction(WrapperNode.GetNode("transaction"), gateway);
            }

            if (WrapperNode.GetNode("disbursement") != null) {
                Disbursement = new Disbursement(WrapperNode.GetNode("disbursement"), gateway);
            }

            if (WrapperNode.GetNode("partner-merchant") != null) {
                PartnerMerchant = new PartnerMerchant(WrapperNode.GetNode("partner-merchant"));
            }

            if (WrapperNode.GetNode("errors") != null) {
                Errors = new ValidationErrors(WrapperNode.GetNode("errors"));
            }

            if (WrapperNode.GetNode("message") != null) {
                Message = WrapperNode.GetString("message");
            }
        }
예제 #15
0
        public WebhookNotification(NodeWrapper node, IBraintreeGateway gateway)
        {
            Timestamp = node.GetDateTime("timestamp");
            Kind      = (WebhookKind)CollectionUtil.Find(WebhookKind.ALL, node.GetString("kind"), WebhookKind.UNRECOGNIZED);

            NodeWrapper WrapperNode = node.GetNode("subject");

            if (WrapperNode.GetNode("api-error-response") != null)
            {
                WrapperNode = WrapperNode.GetNode("api-error-response");
            }

            if (WrapperNode.GetNode("subscription") != null)
            {
                Subscription = new Subscription(WrapperNode.GetNode("subscription"), gateway);
            }

            if (WrapperNode.GetNode("merchant-account") != null)
            {
                MerchantAccount = new MerchantAccount(WrapperNode.GetNode("merchant-account"));
            }

            if (WrapperNode.GetNode("dispute") != null)
            {
                Dispute = new Dispute(WrapperNode.GetNode("dispute"));
            }

            if (WrapperNode.GetNode("transaction") != null)
            {
                Transaction = new Transaction(WrapperNode.GetNode("transaction"), gateway);
            }

            if (WrapperNode.GetNode("disbursement") != null)
            {
                Disbursement = new Disbursement(WrapperNode.GetNode("disbursement"), gateway);
            }

            if (WrapperNode.GetNode("partner-merchant") != null)
            {
                PartnerMerchant = new PartnerMerchant(WrapperNode.GetNode("partner-merchant"));
            }

            if (WrapperNode.GetNode("connected-merchant-status-transitioned") != null)
            {
                ConnectedMerchantStatusTransitioned = new ConnectedMerchantStatusTransitioned(WrapperNode.GetNode("connected-merchant-status-transitioned"));
            }

            if (WrapperNode.GetNode("connected-merchant-paypal-status-changed") != null)
            {
                ConnectedMerchantPayPalStatusChanged = new ConnectedMerchantPayPalStatusChanged(WrapperNode.GetNode("connected-merchant-paypal-status-changed"));
            }

            if (WrapperNode.GetNode("account-updater-daily-report") != null)
            {
                AccountUpdaterDailyReport = new AccountUpdaterDailyReport(WrapperNode.GetNode("account-updater-daily-report"));
            }

            if (WrapperNode.GetNode("ideal-payment") != null)
            {
                IdealPayment = new IdealPayment(WrapperNode.GetNode("ideal-payment"));
            }

            if (WrapperNode.GetNode("errors") != null)
            {
                Errors = new ValidationErrors(WrapperNode.GetNode("errors"));
            }

            if (WrapperNode.GetNode("message") != null)
            {
                Message = WrapperNode.GetString("message");
            }
        }
        public WebhookNotification(NodeWrapper node, IBraintreeGateway gateway)
        {
            Timestamp = node.GetDateTime("timestamp");
            Kind      = (WebhookKind)CollectionUtil.Find(WebhookKind.ALL, node.GetString("kind"), WebhookKind.UNRECOGNIZED);

            NodeWrapper WrapperNode = node.GetNode("subject");

            if (node.GetString("source-merchant-id") != null)
            {
                SourceMerchantId = node.GetString("source-merchant-id");
            }

            if (WrapperNode.GetNode("api-error-response") != null)
            {
                WrapperNode = WrapperNode.GetNode("api-error-response");
            }

            if (WrapperNode.GetNode("subscription") != null)
            {
                Subscription = new Subscription(WrapperNode.GetNode("subscription"), gateway);
            }

            if (WrapperNode.GetNode("merchant-account") != null)
            {
                MerchantAccount = new MerchantAccount(WrapperNode.GetNode("merchant-account"));
            }

            if (WrapperNode.GetNode("dispute") != null)
            {
                Dispute = new Dispute(WrapperNode.GetNode("dispute"));
            }

            if (WrapperNode.GetNode("transaction") != null)
            {
                Transaction = new Transaction(WrapperNode.GetNode("transaction"), gateway);
            }

            if (WrapperNode.GetNode("disbursement") != null)
            {
                Disbursement = new Disbursement(WrapperNode.GetNode("disbursement"), gateway);
            }

            if (WrapperNode.GetNode("partner-merchant") != null)
            {
                PartnerMerchant = new PartnerMerchant(WrapperNode.GetNode("partner-merchant"));
            }

            if (WrapperNode.GetNode("oauth-application-revocation") != null)
            {
                OAuthAccessRevocation = new OAuthAccessRevocation(WrapperNode.GetNode("oauth-application-revocation"));
            }

            if (WrapperNode.GetNode("connected-merchant-status-transitioned") != null)
            {
                ConnectedMerchantStatusTransitioned = new ConnectedMerchantStatusTransitioned(WrapperNode.GetNode("connected-merchant-status-transitioned"));
            }

            if (WrapperNode.GetNode("connected-merchant-paypal-status-changed") != null)
            {
                ConnectedMerchantPayPalStatusChanged = new ConnectedMerchantPayPalStatusChanged(WrapperNode.GetNode("connected-merchant-paypal-status-changed"));
            }

            if (WrapperNode.GetNode("account-updater-daily-report") != null)
            {
                AccountUpdaterDailyReport = new AccountUpdaterDailyReport(WrapperNode.GetNode("account-updater-daily-report"));
            }

            if (WrapperNode.GetNode("ideal-payment") != null)
            {
                IdealPayment = new IdealPayment(WrapperNode.GetNode("ideal-payment"));
            }

            if (WrapperNode.GetNode("granted-payment-instrument-update") != null)
            {
                GrantedPaymentInstrumentUpdate = new GrantedPaymentInstrumentUpdate(WrapperNode.GetNode("granted-payment-instrument-update"));
            }

            if (Kind == WebhookKind.GRANTED_PAYMENT_METHOD_REVOKED)
            {
                RevokedPaymentMethodMetadata = new RevokedPaymentMethodMetadata(WrapperNode, gateway);
            }

            if (WrapperNode.GetNode("errors") != null)
            {
                Errors = new ValidationErrors(WrapperNode.GetNode("errors"));
            }

            if (WrapperNode.GetNode("message") != null)
            {
                Message = WrapperNode.GetString("message");
            }

            if (WrapperNode.GetNode("local-payment") != null)
            {
                LocalPaymentCompleted = new LocalPaymentCompleted(WrapperNode.GetNode("local-payment"));
            }
        }
예제 #17
0
 public virtual void AddErrors(string objectName, ValidationErrors errors)
 {
     nestedErrors[objectName] = errors;
 }
        public void Constructor_ParsesValidationErrorOnNestedObject()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            builder.Append("<api-error-response>");
            builder.Append("  <errors>");
            builder.Append("    <errors type=\"array\"/>");
            builder.Append("    <credit-card>");
            builder.Append("      <billing-address>");
            builder.Append("        <errors type=\"array\">");
            builder.Append("          <error>");
            builder.Append("            <code>91803</code>");
            builder.Append("            <message>Country name is not an accepted country.</message>");
            builder.Append("            <attribute type=\"symbol\">country_name</attribute>");
            builder.Append("          </error>");
            builder.Append("        </errors>");
            builder.Append("      </billing-address>");
            builder.Append("      <errors type=\"array\"/>");
            builder.Append("    </credit-card>");
            builder.Append("  </errors>");
            builder.Append("</api-error-response>");

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(builder.ToString());
            ValidationErrors errors = new ValidationErrors(new NodeWrapper(doc.ChildNodes[1]));
            Assert.AreEqual(1, errors.DeepCount);
            Assert.AreEqual(ValidationErrorCode.ADDRESS_COUNTRY_NAME_IS_NOT_ACCEPTED, errors.ForObject("credit-card").ForObject("billing-address").OnField("country_name")[0].Code);
        }
        public void Constructor_ParsesMultipleErrorsOnSingleField()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            builder.Append("<api-error-response>");
            builder.Append("  <errors>");
            builder.Append("    <transaction>");
            builder.Append("      <errors type=\"array\">");
            builder.Append("        <error>");
            builder.Append("          <code>91516</code>");
            builder.Append("          <message>Cannot provide both payment_method_token and customer_id unless the payment_method belongs to the customer.</message>");
            builder.Append("          <attribute type=\"symbol\">base</attribute>");
            builder.Append("        </error>");
            builder.Append("        <error>");
            builder.Append("          <code>91515</code>");
            builder.Append("          <message>Cannot provide both payment_method_token and credit_card attributes.</message>");
            builder.Append("          <attribute type=\"symbol\">base</attribute>");
            builder.Append("        </error>");
            builder.Append("      </errors>");
            builder.Append("    </transaction>");
            builder.Append("    <errors type=\"array\"/>");
            builder.Append("  </errors>");
            builder.Append("</api-error-response>");

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(builder.ToString());
            ValidationErrors errors = new ValidationErrors(new NodeWrapper(doc.ChildNodes[1]));
            Assert.AreEqual(2, errors.DeepCount);
            Assert.AreEqual(2, errors.ForObject("transaction").OnField("base").Count);
        }
 public virtual void AddErrors(string objectName, ValidationErrors errors)
 {
     nestedErrors[objectName] = errors;
 }
        public WebhookNotification(NodeWrapper node, IBraintreeGateway gateway)
        {
            Timestamp = node.GetDateTime("timestamp");
            Kind      = (WebhookKind)CollectionUtil.Find(WebhookKind.ALL, node.GetString("kind"), WebhookKind.UNRECOGNIZED);

            NodeWrapper WrapperNode = node.GetNode("subject");

            if (node.GetString("source-merchant-id") != null)
            {
                SourceMerchantId = node.GetString("source-merchant-id");
            }

            if (WrapperNode.GetNode("api-error-response") != null)
            {
                WrapperNode = WrapperNode.GetNode("api-error-response");
            }

            if (WrapperNode.GetNode("subscription") != null)
            {
                Subscription = new Subscription(WrapperNode.GetNode("subscription"), gateway);
            }

            if (WrapperNode.GetNode("merchant-account") != null)
            {
                MerchantAccount = new MerchantAccount(WrapperNode.GetNode("merchant-account"));
            }

            if (WrapperNode.GetNode("dispute") != null)
            {
                Dispute = new Dispute(WrapperNode.GetNode("dispute"));
            }

            if (WrapperNode.GetNode("transaction") != null)
            {
                Transaction = new Transaction(WrapperNode.GetNode("transaction"), gateway);
            }

            if (WrapperNode.GetNode("disbursement") != null)
            {
                Disbursement = new Disbursement(WrapperNode.GetNode("disbursement"), gateway);
            }

            if (WrapperNode.GetNode("partner-merchant") != null)
            {
                PartnerMerchant = new PartnerMerchant(WrapperNode.GetNode("partner-merchant"));
            }

            if (WrapperNode.GetNode("oauth-application-revocation") != null)
            {
                OAuthAccessRevocation = new OAuthAccessRevocation(WrapperNode.GetNode("oauth-application-revocation"));
            }

            if (WrapperNode.GetNode("connected-merchant-status-transitioned") != null)
            {
                ConnectedMerchantStatusTransitioned = new ConnectedMerchantStatusTransitioned(WrapperNode.GetNode("connected-merchant-status-transitioned"));
            }

            if (WrapperNode.GetNode("connected-merchant-paypal-status-changed") != null)
            {
                ConnectedMerchantPayPalStatusChanged = new ConnectedMerchantPayPalStatusChanged(WrapperNode.GetNode("connected-merchant-paypal-status-changed"));
            }

            if (WrapperNode.GetNode("account-updater-daily-report") != null)
            {
                AccountUpdaterDailyReport = new AccountUpdaterDailyReport(WrapperNode.GetNode("account-updater-daily-report"));
            }

            // NEXT_MAJOR_VERSION Remove this class as legacy Ideal has been removed/disabled in the Braintree Gateway
            // DEPRECATED If you're looking to accept iDEAL as a payment method contact [email protected] for a solution.
            if (WrapperNode.GetNode("ideal-payment") != null)
            {
                IdealPayment = new IdealPayment(WrapperNode.GetNode("ideal-payment"));
            }

            if (WrapperNode.GetNode("granted-payment-instrument-update") != null)
            {
                GrantedPaymentInstrumentUpdate = new GrantedPaymentInstrumentUpdate(WrapperNode.GetNode("granted-payment-instrument-update"));
            }

            if (Kind == WebhookKind.GRANTED_PAYMENT_METHOD_REVOKED || Kind == WebhookKind.PAYMENT_METHOD_REVOKED_BY_CUSTOMER)
            {
                RevokedPaymentMethodMetadata = new RevokedPaymentMethodMetadata(WrapperNode, gateway);
            }

            if (WrapperNode.GetNode("errors") != null)
            {
                Errors = new ValidationErrors(WrapperNode.GetNode("errors"));
            }

            if (WrapperNode.GetNode("message") != null)
            {
                Message = WrapperNode.GetString("message");
            }

            if (WrapperNode.GetNode("local-payment") != null)
            {
                LocalPaymentCompleted = new LocalPaymentCompleted(WrapperNode.GetNode("local-payment"), gateway);
            }
        }