Repository: saleor/saleor

Issue:
Have the API return `null` instead of a placeholder when an image is missing
### What I'm trying to achieve
There's no reason the backend server should decide how to handle a missing image and what image would fit as a placeholder if a placeholder is needed.

### Describe a proposed solution
Have the GraphQL API return `null` when no image is present instead of falling back to a placeholder image.


Discussion:
Can I take this up? This will be my first time in GraphQL so hopefully you can be patient with me. =)
Absolutely, feel free to take it. Let us know if you need any help. Good luck 👍 
For starters which API's are currently returning placeholder images?
Thumbnail fields return placeholders.

An example:
```graphql
{
  products(first: 10) {
    edges {
      node {
        id
        name
        thumbnail {
          url
        }
      }
    }
  }
}

```

Resolving patch:
diff --git a/saleor/graphql/order/types.py b/saleor/graphql/order/types.py
--- a/saleor/graphql/order/types.py
+++ b/saleor/graphql/order/types.py
@@ -228,15 +228,15 @@ class Meta:
     @gql_optimizer.resolver_hints(
         prefetch_related=["variant__images", "variant__product__images"]
     )
-    def resolve_thumbnail(root: models.OrderLine, info, *, size=None):
+    def resolve_thumbnail(root: models.OrderLine, info, *, size=255):
         if not root.variant_id:
             return None
-        if not size:
-            size = 255
         image = root.variant.get_first_image()
-        url = get_product_image_thumbnail(image, size, method="thumbnail")
-        alt = image.alt if image else None
-        return Image(alt=alt, url=info.context.build_absolute_uri(url))
+        if image:
+            url = get_product_image_thumbnail(image, size, method="thumbnail")
+            alt = image.alt
+            return Image(alt=alt, url=info.context.build_absolute_uri(url))
+        return None
 
     @staticmethod
     def resolve_unit_price(root: models.OrderLine, _info):
diff --git a/saleor/graphql/product/types/products.py b/saleor/graphql/product/types/products.py
--- a/saleor/graphql/product/types/products.py
+++ b/saleor/graphql/product/types/products.py
@@ -512,14 +512,13 @@ def resolve_tax_type(root: models.Product, info):
 
     @staticmethod
     @gql_optimizer.resolver_hints(prefetch_related="images")
-    def resolve_thumbnail(root: models.Product, info, *, size=None):
+    def resolve_thumbnail(root: models.Product, info, *, size=255):
         image = root.get_first_image()
-        if not size:
-            size = 255
-        url = get_product_image_thumbnail(image, size, method="thumbnail")
-        url = info.context.build_absolute_uri(url)
-        alt = image.alt if image else None
-        return Image(alt=alt, url=url)
+        if image:
+            url = get_product_image_thumbnail(image, size, method="thumbnail")
+            alt = image.alt
+            return Image(alt=alt, url=info.context.build_absolute_uri(url))
+        return None
 
     @staticmethod
     def resolve_url(root: models.Product, *_args):


Test patch:
diff --git a/tests/api/test_order.py b/tests/api/test_order.py
--- a/tests/api/test_order.py
+++ b/tests/api/test_order.py
@@ -109,10 +109,7 @@ def test_orderline_query(staff_api_client, permission_manage_orders, fulfilled_o
     response = staff_api_client.post_graphql(query)
     content = get_graphql_content(response)
     order_data = content["data"]["orders"]["edges"][0]["node"]
-    assert (
-        "/static/images/placeholder540x540.png"
-        in order_data["lines"][0]["thumbnail"]["url"]
-    )
+    assert order_data["lines"][0]["thumbnail"] is None
     variant_id = graphene.Node.to_global_id("ProductVariant", line.variant.pk)
     assert order_data["lines"][0]["variant"]["id"] == variant_id