Repository: saleor/saleor

Issue:
Required field names should be consistent with AddressInput
### What I'm trying to achieve
Get required fields for shipping address

### Steps to reproduce the problem
1. Send query 
```
query {
  addressValidator(input: {countryCode: "US", countryArea: "", cityArea: ""}) {
    requiredFields
  }
}
```
2.  Look at the response
```
{
  "data": {
    "addressValidator": {
      "requiredFields": [
        "city",
        "street_address",
        "country_area",
        "postal_code"
      ]
    }
  }
}
```

### What I expected to happen
Get consistent names with AddressInput.
Something like following:
```
{
  "data": {
    "addressValidator": {
      "requiredFields": [
        "city",
        "streetAddress1",
        "countryArea",
        "postalCode"
      ]
    }
  }
}
```

### Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->
<img width="1355" alt="image" src="https://user-images.githubusercontent.com/8916015/61969831-bc198b00-afdb-11e9-99a5-b8d6af183151.png">


**System information**
Operating system: MacOS
Browser: Firefox



Discussion:

Resolving patch:
diff --git a/saleor/graphql/account/resolvers.py b/saleor/graphql/account/resolvers.py
--- a/saleor/graphql/account/resolvers.py
+++ b/saleor/graphql/account/resolvers.py
@@ -1,11 +1,11 @@
 from itertools import chain
+from typing import Optional
 
 import graphene_django_optimizer as gql_optimizer
 from django.db.models import Q
 from i18naddress import get_validation_rules
 
 from ...account import models
-from ...core.utils import get_client_ip, get_country_by_ip
 from ...payment.utils import (
     fetch_customer_id,
     list_enabled_gateways,
@@ -13,6 +13,7 @@
 )
 from ..utils import filter_by_query_param
 from .types import AddressValidationData, ChoiceValue
+from .utils import get_allowed_fields_camel_case, get_required_fields_camel_case
 
 USER_SEARCH_FIELDS = (
     "email",
@@ -47,17 +48,17 @@ def resolve_staff_users(info, query):
     return gql_optimizer.query(qs, info)
 
 
-def resolve_address_validator(info, country_code, country_area, city_area):
-    if not country_code:
-        client_ip = get_client_ip(info.context)
-        country = get_country_by_ip(client_ip)
-        if country:
-            country_code = country.code
-        else:
-            return None
+def resolve_address_validation_rules(
+    info,
+    country_code: str,
+    country_area: Optional[str],
+    city: Optional[str],
+    city_area: Optional[str],
+):
     params = {
         "country_code": country_code,
         "country_area": country_area,
+        "city": city,
         "city_area": city_area,
     }
     rules = get_validation_rules(params)
@@ -66,8 +67,8 @@ def resolve_address_validator(info, country_code, country_area, city_area):
         country_name=rules.country_name,
         address_format=rules.address_format,
         address_latin_format=rules.address_latin_format,
-        allowed_fields=rules.allowed_fields,
-        required_fields=rules.required_fields,
+        allowed_fields=get_allowed_fields_camel_case(rules.allowed_fields),
+        required_fields=get_required_fields_camel_case(rules.required_fields),
         upper_fields=rules.upper_fields,
         country_area_type=rules.country_area_type,
         country_area_choices=[
diff --git a/saleor/graphql/account/schema.py b/saleor/graphql/account/schema.py
--- a/saleor/graphql/account/schema.py
+++ b/saleor/graphql/account/schema.py
@@ -48,7 +48,11 @@
     UserClearStoredPrivateMeta,
     UserUpdatePrivateMeta,
 )
-from .resolvers import resolve_address_validator, resolve_customers, resolve_staff_users
+from .resolvers import (
+    resolve_address_validation_rules,
+    resolve_customers,
+    resolve_staff_users,
+)
 from .types import AddressValidationData, User
 
 
@@ -65,9 +69,10 @@ class Meta:
 class AccountQueries(graphene.ObjectType):
     address_validation_rules = graphene.Field(
         AddressValidationData,
-        country_code=graphene.Argument(CountryCodeEnum, required=False),
-        country_area=graphene.String(required=False),
-        city_area=graphene.String(required=False),
+        country_code=graphene.Argument(CountryCodeEnum, required=True),
+        country_area=graphene.Argument(graphene.String),
+        city=graphene.Argument(graphene.String),
+        city_area=graphene.Argument(graphene.String),
     )
     customers = FilterInputConnectionField(
         User,
@@ -89,12 +94,13 @@ class AccountQueries(graphene.ObjectType):
     )
 
     def resolve_address_validation_rules(
-        self, info, country_code=None, country_area=None, city_area=None
+        self, info, country_code, country_area=None, city=None, city_area=None
     ):
-        return resolve_address_validator(
+        return resolve_address_validation_rules(
             info,
-            country_code=country_code,
+            country_code,
             country_area=country_area,
+            city=city,
             city_area=city_area,
         )
 
diff --git a/saleor/graphql/account/utils.py b/saleor/graphql/account/utils.py
--- a/saleor/graphql/account/utils.py
+++ b/saleor/graphql/account/utils.py
@@ -1,4 +1,5 @@
 from django.core.exceptions import ValidationError
+from graphene.utils.str_converters import to_camel_case
 
 from ...account import events as account_events
 
@@ -42,3 +43,24 @@ def clean_instance(cls, info, instance):
         super().clean_instance(info, instance)
         if not instance.is_staff:
             raise ValidationError({"id": "Cannot delete a non-staff user."})
+
+
+def get_required_fields_camel_case(required_fields: set) -> set:
+    """Return set of AddressValidationRules required fields in camel case."""
+    return {validation_field_to_camel_case(field) for field in required_fields}
+
+
+def validation_field_to_camel_case(name: str) -> str:
+    """Convert name of the field from snake case to camel case."""
+    name = to_camel_case(name)
+    if name == "streetAddress":
+        return "streetAddress1"
+    return name
+
+
+def get_allowed_fields_camel_case(allowed_fields: set) -> set:
+    """Return set of AddressValidationRules allowed fields in camel case."""
+    fields = {validation_field_to_camel_case(field) for field in allowed_fields}
+    if "streetAddress1" in fields:
+        fields.add("streetAddress2")
+    return fields


Test patch:
diff --git a/tests/api/test_account.py b/tests/api/test_account.py
--- a/tests/api/test_account.py
+++ b/tests/api/test_account.py
@@ -1793,10 +1793,10 @@ def test_set_default_address(
     assert data["user"]["defaultShippingAddress"]["id"] == address_id
 
 
-def test_address_validator(user_api_client):
+def test_address_validation_rules(user_api_client):
     query = """
     query getValidator(
-        $country_code: CountryCode, $country_area: String, $city_area: String) {
+        $country_code: CountryCode!, $country_area: String, $city_area: String) {
         addressValidationRules(
                 countryCode: $country_code,
                 countryArea: $country_area,
@@ -1822,42 +1822,10 @@ def test_address_validator(user_api_client):
     assert matcher.match("00-123")
 
 
-def test_address_validator_uses_geip_when_country_code_missing(
-    user_api_client, monkeypatch
-):
-    query = """
-    query getValidator(
-        $country_code: CountryCode, $country_area: String, $city_area: String) {
-        addressValidationRules(
-                countryCode: $country_code,
-                countryArea: $country_area,
-                cityArea: $city_area) {
-            countryCode,
-            countryName
-        }
-    }
-    """
-    variables = {"country_code": None, "country_area": None, "city_area": None}
-    mock_country_by_ip = Mock(return_value=Mock(code="US"))
-    monkeypatch.setattr(
-        "saleor.graphql.account.resolvers.get_client_ip",
-        lambda request: Mock(return_value="127.0.0.1"),
-    )
-    monkeypatch.setattr(
-        "saleor.graphql.account.resolvers.get_country_by_ip", mock_country_by_ip
-    )
-    response = user_api_client.post_graphql(query, variables)
-    content = get_graphql_content(response)
-    assert mock_country_by_ip.called
-    data = content["data"]["addressValidationRules"]
-    assert data["countryCode"] == "US"
-    assert data["countryName"] == "UNITED STATES"
-
-
-def test_address_validator_with_country_area(user_api_client):
+def test_address_validation_rules_with_country_area(user_api_client):
     query = """
     query getValidator(
-        $country_code: CountryCode, $country_area: String, $city_area: String) {
+        $country_code: CountryCode!, $country_area: String, $city_area: String) {
         addressValidationRules(
                 countryCode: $country_code,
                 countryArea: $country_area,
@@ -1900,6 +1868,28 @@ def test_address_validator_with_country_area(user_api_client):
     assert not data["cityAreaChoices"]
 
 
+def test_address_validation_rules_fields_in_camel_case(user_api_client):
+    query = """
+    query getValidator(
+        $country_code: CountryCode!) {
+        addressValidationRules(countryCode: $country_code) {
+            requiredFields
+            allowedFields
+        }
+    }
+    """
+    variables = {"country_code": "PL"}
+    response = user_api_client.post_graphql(query, variables)
+    content = get_graphql_content(response)
+    data = content["data"]["addressValidationRules"]
+    required_fields = data["requiredFields"]
+    allowed_fields = data["allowedFields"]
+    assert "streetAddress1" in required_fields
+    assert "streetAddress2" not in required_fields
+    assert "streetAddress1" in allowed_fields
+    assert "streetAddress2" in allowed_fields
+
+
 CUSTOMER_PASSWORD_RESET_MUTATION = """
     mutation CustomerPasswordReset($email: String!) {
         customerPasswordReset(input: {email: $email}) {