Skip to content

Format :email for type :string is not enforced during validation #694

@arturo-medina-merino

Description

@arturo-medina-merino

Hello all 👋 ,

The library documentation includes the format: :email as an example: (https://hexdocs.pm/open_api_spex/OpenApiSpex.Schema.html#module-examples), so you would expect for it to be supported, but, it seems that this is not the case.

defmodule TestOpenApiSpex.Schemas.User do
  require OpenApiSpex
  alias OpenApiSpex.Schema

  OpenApiSpex.schema(%{
    title: "User",
    type: :object,
    properties: %{
      email: %Schema{
        type: :string,
        format: :email
      }
    },
    required: [:email]
  })
end

All the following tests pass (regardless of containing incorrect emails):

defmodule UserSchemaTest do
  use ExUnit.Case

  alias TestOpenApiSpex.Schemas.User

  describe "email format validation" do
    test "valid email passes validation" do
      result = OpenApiSpex.cast_value(%{"email" => "user@example.com"}, User.schema())

      assert {:ok, _} = result
    end

    test "invalid email - demonstrates format is NOT validated" do
      result = OpenApiSpex.cast_value(%{"email" => "not-an-email"}, User.schema())

      assert {:ok, _} = result
    end

    test "completely invalid string passes as email" do
      result = OpenApiSpex.cast_value(%{"email" => "random string with spaces"}, User.schema())

      assert {:ok, _} = result
    end

    test "empty string passes as email" do
      result = OpenApiSpex.cast_value(%{"email" => ""}, User.schema())

      assert {:ok, _} = result
    end

    test "missing required email field fails validation" do
      result = OpenApiSpex.cast_value(%{}, User.schema())

      assert {:error, [%OpenApiSpex.Cast.Error{reason: :missing_field} | other_errors]} =
               result

      assert length(other_errors) == 0
    end

    test "non-string type fails validation" do
      result = OpenApiSpex.cast_value(%{"email" => 123}, User.schema())

      assert {:error, [%OpenApiSpex.Cast.Error{reason: :invalid_type} | other_errors]} = result
      assert length(other_errors) == 0
    end
  end
end

According to the official OpenAPI specification, "email" is not part of the standard format values. See https://swagger.io/docs/specification/v3_0/data-models/data-types/

However, format is an open value, so you can use any formats, even not those defined by the OpenAPI Specification, such as:
email
uuid
uri
hostname
ipv4
ipv6
and others

I would say that, at the very least, the examples should be modified to avoid confusion, but ideally, the :email format should be implemented, as it is very common and implementable with an "easy" regex.

Many thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions