require 'test_helper'

class FormatTest < Minitest::Test
  def test_it_allows_disabling_format
    schema = JSONSchemer.schema(
      { 'format' => 'email' },
      format: false
    )
    assert(schema.valid?('not-an-email'))
  end

  def test_it_ignores_format_for_invalid_type
    schema = JSONSchemer.schema({
      'format' => 'email'
    })
    refute(schema.valid?('not-an-email'))
    assert(schema.valid?({}))
  end

  def test_it_ignores_unknown_format
    schemer = JSONSchemer.schema({ 'type' => 'string', 'format' => 'unknown' })
    assert(schemer.valid?('1'))
    refute(schemer.valid?(1))
    schemer = JSONSchemer.schema({ 'maximum' => 1, 'format' => 'unknown' })
    assert(schemer.valid?(1))
    refute(schemer.valid?(2))
  end

  def test_format_assertion_raises_unknown_format
    annotation = {
      '$vocabulary' => {
        'https://json-schema.org/draft/2020-12/vocab/format-annotation' => true
      }
    }
    assertion = {
      '$vocabulary' => {
        'https://json-schema.org/draft/2020-12/vocab/format-assertion' => true
      }
    }
    schema = {
      '$schema' => 'http://example.com',
      'format' => 'unknown'
    }
    assert(JSONSchemer.schema(schema, :ref_resolver => proc { annotation }).valid?('x'))
    assert_raises(JSONSchemer::UnknownFormat) { JSONSchemer.schema(schema, :ref_resolver => proc { assertion }) }
  end

  def test_it_validates_spaces_in_uri_format
    schema = JSONSchemer.schema({ 'format' => 'uri' })
    refute(schema.valid?('http://example.com?sp ce'))
    refute(schema.valid?('mailto:sp ce@example.com'))
  end

  def test_it_allows_false_custom_format
    schema = JSONSchemer.schema(
      {
        'type' => 'object',
        'properties' => {
          'one' => {
            'format' => 'email'
          },
          'two' => {
            'format' => 'time'
          }
        }
      },
      formats: {
        'email' => false
      }
    )
    data = {
      'one' => 'not-an-email',
      'two' => 'not-a-time'
    }
    errors = schema.validate(data).to_a
    assert_equal(1, errors.size)
    assert_equal('not-a-time', errors.first.fetch('data'))
    assert_equal('format', errors.first.fetch('type'))
  end

  def test_it_allows_callable_custom_format
    schema = JSONSchemer.schema(
      { 'format' => 'custom' },
      formats: {
        'custom' => proc { |x| x == 'valid' }
      }
    )
    assert(schema.valid?('valid'))
    refute(schema.valid?('invalid'))
  end

  def test_email_format
    schema = JSONSchemer.schema({ 'format' => 'email' })

    {
      "joe.bloggs@example.com" => true,
      "2962" => false,
      "te~st@example.com" => true,
      "~test@example.com" => true,
      "test~@example.com" => true,
      "\"joe bloggs\"@example.com" => true,
      "\"joe..bloggs\"@example.com" => true,
      "\"joe@bloggs\"@example.com" => true,
      "joe.bloggs@[127.0.0.1]" => true,
      "joe.bloggs@[IPv6:::1]" => true,
      ".test@example.com" => false,
      "test.@example.com" => false,
      "te.s.t@example.com" => true,
      "te..st@example.com" => false,
      "joe.bloggs@invalid=domain.com" => false,
      "joe.bloggs@[127.0.0.300]" => false
    }.each do |email, valid|
      assert_equal(valid, schema.valid?(email))
    end
  end

  def test_rfc3339_vs_iso8601
    # generated via: https://ijmacd.github.io/rfc3339-iso8601/
    rfc3339_dates = Set[
      '2023-11-01'
    ]
    rfc3339_times = Set[
      '11:24:25-07:00',
      '11:24:25.5-07:00',
      '11:24:25.50-07:00',
      '11:24:25.500-07:00',
      '11:24:25.500623-07:00',
      '18:24:25Z',
      '18:24:25.5Z',
      '18:24:25.50Z',
      '18:24:25.500Z',
      '18:24:25.500623Z',
      '18:24:25+00:00',
      '18:24:25.5+00:00',
      '18:24:25.500+00:00',
      '18:24:25.500623+00:00',
      '18:24:25-00:00',
      '18:24:25.5-00:00',
      '18:24:25.500-00:00',
      '18:24:25.500623-00:00'
    ]
    rfc3339_date_times = Set[
      '2023-11-01T18:24:25Z',
      '2023-11-01T18:24:25.5Z',
      '2023-11-01T18:24:25.50Z',
      '2023-11-01T18:24:25.500Z',
      '2023-11-01T18:24:25.500623Z',
      '2023-11-01t18:24:25z',
      '2023-11-01t18:24:25.500z',
      '2023-11-01T11:24:25-07:00',
      '2023-11-01T11:24:25.5-07:00',
      '2023-11-01T11:24:25.50-07:00',
      '2023-11-01T11:24:25.500-07:00',
      '2023-11-01T11:24:25.500623-07:00',
      '2023-11-01 11:24:25-07:00',
      '2023-11-01 11:24:25.5-07:00',
      '2023-11-01 11:24:25.50-07:00',
      '2023-11-01 11:24:25.500-07:00',
      '2023-11-01 11:24:25.500623-07:00',
      '2023-11-01 18:24:25Z',
      # '2023-11-01_18:24:25Z',
      '2023-11-01 18:24:25z',
      # '2023-11-01_18:24:25z',
      '2023-11-01 18:24:25.5Z',
      '2023-11-01 18:24:25.50Z',
      '2023-11-01 18:24:25.500Z',
      # '2023-11-01_18:24:25.500Z',
      '2023-11-01 18:24:25.500623Z',
      # '2023-11-01_18:24:25.500623Z',
      '2023-11-01 18:24:25.500z',
      # '2023-11-01_18:24:25.500z',
      '2023-11-01 18:24:25.500623z',
      # '2023-11-01_18:24:25.500623z',
      '2023-11-01 18:24:25-00:00',
      '2023-11-01 18:24:25.500-00:00',
      '2023-11-01T18:24:25-00:00',
      '2023-11-01T18:24:25.500-00:00',
      '2023-11-02T03:09:25+08:45',
      '2023-11-01T18:24:25+00:00',
      '2023-11-01T18:24:25.500+00:00'
    ]
    iso8601_dates = Set[
      '2023-11-01',
      '20',
      '202',
      '2023',
      '2023-11',
      '2023-305',
      '2023-W44',
      '2023-W44-3',
      '20231101',
      '2023305',
      '2023W44',
      '2023W443'
    ]
    iso8601_times = Set[
      '11:24:25-07:00',
      '11:24:25.5-07:00',
      '11:24:25.50-07:00',
      '11:24:25.500-07:00',
      '11:24:25.500623-07:00',
      '18:24:25Z',
      '18:24:25.5Z',
      '18:24:25.50Z',
      '18:24:25.500Z',
      '18:24:25.500623Z',
      '18:24:25+00:00',
      '18:24:25.5+00:00',
      '18:24:25.500+00:00',
      '18:24:25.500623+00:00',
      '11',
      '11,4',
      '11.4',
      '11:24',
      '11:24,4',
      '11:24.4',
      '11:24:25',
      '11:24:25.5',
      '11:24:25.50',
      '11:24:25,500',
      '11:24:25.500',
      '11:24:25,500623',
      '11:24:25.500623',
      '18Z',
      '18,4Z',
      '18.4Z',
      '18:24Z',
      '18:24,4Z',
      '18:24.4Z',
      '18:24:25,500Z',
      '18:24:25,500623Z',
      '11-07',
      '11,4-07',
      '11.4-07',
      '11:24-07',
      '11:24,4-07',
      '11:24.4-07',
      '11:24:25-07',
      '11:24:25.5-07',
      '11:24:25.50-07',
      '11:24:25,500-07',
      '11:24:25.500-07',
      '11:24:25,500623-07',
      '11:24:25.500623-07',
      '11-07:00',
      '11,4-07:00',
      '11.4-07:00',
      '11:24-07:00',
      '11:24,4-07:00',
      '11:24.4-07:00',
      '11:24:25,500-07:00',
      '11:24:25,500623-07:00',
      'T11',
      'T11,4',
      'T11.4',
      'T11:24',
      'T11:24,4',
      'T11:24.4',
      'T11:24:25',
      'T11:24:25.5',
      'T11:24:25.50',
      'T11:24:25,500',
      'T11:24:25.500',
      'T11:24:25,500623',
      'T11:24:25.500623',
      'T18Z',
      'T18,4Z',
      'T18.4Z',
      'T18:24Z',
      'T18:24,4Z',
      'T18:24.4Z',
      'T18:24:25Z',
      'T18:24:25.5Z',
      'T18:24:25.50Z',
      'T18:24:25,500Z',
      'T18:24:25.500Z',
      'T18:24:25,500623Z',
      'T18:24:25.500623Z',
      'T11-07',
      'T11,4-07',
      'T11.4-07',
      'T11:24-07',
      'T11:24,4-07',
      'T11:24.4-07',
      'T11:24:25-07',
      'T11:24:25.5-07',
      'T11:24:25.50-07',
      'T11:24:25,500-07',
      'T11:24:25.500-07',
      'T11:24:25,500623-07',
      'T11:24:25.500623-07',
      'T11-07:00',
      'T11,4-07:00',
      'T11.4-07:00',
      'T11:24-07:00',
      'T11:24,4-07:00',
      'T11:24.4-07:00',
      'T11:24:25-07:00',
      'T11:24:25.5-07:00',
      'T11:24:25.50-07:00',
      'T11:24:25,500-07:00',
      'T11:24:25.500-07:00',
      'T11:24:25,500623-07:00',
      'T11:24:25.500623-07:00',
      '1124',
      '1124,4',
      '1124.4',
      '112425',
      '112425.5',
      '112425.50',
      '112425,500',
      '112425.500',
      '112425,500623',
      '112425.500623',
      '1824Z',
      '1824,4Z',
      '1824.4Z',
      '182425Z',
      '182425.5Z',
      '182425.50Z',
      '182425,500Z',
      '182425.500Z',
      '182425,500623Z',
      '182425.500623Z',
      '1124-07',
      '1124,4-07',
      '1124.4-07',
      '112425-07',
      '112425.5-07',
      '112425.50-07',
      '112425,500-07',
      '112425.500-07',
      '112425,500623-07',
      '112425.500623-07',
      '11-0700',
      '11,4-0700',
      '11.4-0700',
      '1124-0700',
      '1124,4-0700',
      '1124.4-0700',
      '112425-0700',
      '112425.5-0700',
      '112425.50-0700',
      '112425,500-0700',
      '112425.500-0700',
      '112425,500623-0700',
      '112425.500623-0700',
      'T1124',
      'T1124,4',
      'T1124.4',
      'T112425',
      'T112425.5',
      'T112425.50',
      'T112425,500',
      'T112425.500',
      'T112425,500623',
      'T112425.500623',
      'T1824Z',
      'T1824,4Z',
      'T1824.4Z',
      'T182425Z',
      'T182425.5Z',
      'T182425.50Z',
      'T182425,500Z',
      'T182425.500Z',
      'T182425,500623Z',
      'T182425.500623Z',
      'T1124-07',
      'T1124,4-07',
      'T1124.4-07',
      'T112425-07',
      'T112425.5-07',
      'T112425.50-07',
      'T112425,500-07',
      'T112425.500-07',
      'T112425,500623-07',
      'T112425.500623-07',
      'T11-0700',
      'T11,4-0700',
      'T11.4-0700',
      'T1124-0700',
      'T1124,4-0700',
      'T1124.4-0700',
      'T112425-0700',
      'T112425.5-0700',
      'T112425.50-0700',
      'T112425,500-0700',
      'T112425.500-0700',
      'T112425,500623-0700',
      'T112425.500623-0700'
    ]
    iso8601_date_times = Set[
      '2023-11-01T18:24:25Z',
      '2023-11-01T18:24:25.5Z',
      '2023-11-01T18:24:25.50Z',
      '2023-11-01T18:24:25.500Z',
      '2023-11-01T18:24:25.500623Z',
      '2023-11-01T11:24:25-07:00',
      '2023-11-01T11:24:25.500-07:00',
      '2023-11-01T11:24:25.500623-07:00',
      '2023-11-02T03:09:25+08:45',
      '2023-11-01T18:24:25+00:00',
      '2023-11-01T18:24:25.500+00:00',
      '2023-11-01T11',
      '2023-11-01T11,4',
      '2023-11-01T11.4',
      '2023-11-01T11:24',
      '2023-11-01T11:24,4',
      '2023-11-01T11:24.4',
      '2023-11-01T11:24:25',
      '2023-11-01T11:24:25.5',
      '2023-11-01T11:24:25.50',
      '2023-11-01T11:24:25,500',
      '2023-11-01T11:24:25.500',
      '2023-11-01T11:24:25,500623',
      '2023-11-01T11:24:25.500623',
      '2023-11-01T18Z',
      '2023-11-01T18,4Z',
      '2023-11-01T18.4Z',
      '2023-11-01T18:24Z',
      '2023-11-01T18:24,4Z',
      '2023-11-01T18:24.4Z',
      '2023-11-01T18:24:25,500Z',
      '2023-11-01T18:24:25,500623Z',
      '2023-11-01T11-07',
      '2023-11-01T11,4-07',
      '2023-11-01T11.4-07',
      '2023-11-01T11:24-07',
      '2023-11-01T11:24,4-07',
      '2023-11-01T11:24.4-07',
      '2023-11-01T11:24:25-07',
      '2023-11-01T11:24:25.5-07',
      '2023-11-01T11:24:25.50-07',
      '2023-11-01T11:24:25,500-07',
      '2023-11-01T11:24:25.500-07',
      '2023-11-01T11:24:25,500623-07',
      '2023-11-01T11:24:25.500623-07',
      '2023-11-01T11-07:00',
      '2023-11-01T11,4-07:00',
      '2023-11-01T11.4-07:00',
      '2023-11-01T11:24-07:00',
      '2023-11-01T11:24,4-07:00',
      '2023-11-01T11:24.4-07:00',
      '2023-11-01T11:24:25.5-07:00',
      '2023-11-01T11:24:25.50-07:00',
      '2023-11-01T11:24:25,500-07:00',
      '2023-11-01T11:24:25,500623-07:00',
      '2023-W44-3T11',
      '2023-W44-3T11,4',
      '2023-W44-3T11.4',
      '2023-W44-3T11:24',
      '2023-W44-3T11:24,4',
      '2023-W44-3T11:24.4',
      '2023-W44-3T11:24:25',
      '2023-W44-3T11:24:25.5',
      '2023-W44-3T11:24:25.50',
      '2023-W44-3T11:24:25,500',
      '2023-W44-3T11:24:25.500',
      '2023-W44-3T11:24:25,500623',
      '2023-W44-3T11:24:25.500623',
      '2023-W44-3T18Z',
      '2023-W44-3T18,4Z',
      '2023-W44-3T18.4Z',
      '2023-W44-3T18:24Z',
      '2023-W44-3T18:24,4Z',
      '2023-W44-3T18:24.4Z',
      '2023-W44-3T18:24:25Z',
      '2023-W44-3T18:24:25.5Z',
      '2023-W44-3T18:24:25.50Z',
      '2023-W44-3T18:24:25,500Z',
      '2023-W44-3T18:24:25.500Z',
      '2023-W44-3T18:24:25,500623Z',
      '2023-W44-3T18:24:25.500623Z',
      '2023-W44-3T11-07',
      '2023-W44-3T11,4-07',
      '2023-W44-3T11.4-07',
      '2023-W44-3T11:24-07',
      '2023-W44-3T11:24,4-07',
      '2023-W44-3T11:24.4-07',
      '2023-W44-3T11:24:25-07',
      '2023-W44-3T11:24:25.5-07',
      '2023-W44-3T11:24:25.50-07',
      '2023-W44-3T11:24:25,500-07',
      '2023-W44-3T11:24:25.500-07',
      '2023-W44-3T11:24:25,500623-07',
      '2023-W44-3T11:24:25.500623-07',
      '2023-W44-3T11-07:00',
      '2023-W44-3T11,4-07:00',
      '2023-W44-3T11.4-07:00',
      '2023-W44-3T11:24-07:00',
      '2023-W44-3T11:24,4-07:00',
      '2023-W44-3T11:24.4-07:00',
      '2023-W44-3T11:24:25-07:00',
      '2023-W44-3T11:24:25.5-07:00',
      '2023-W44-3T11:24:25.50-07:00',
      '2023-W44-3T11:24:25,500-07:00',
      '2023-W44-3T11:24:25.500-07:00',
      '2023-W44-3T11:24:25,500623-07:00',
      '2023-W44-3T11:24:25.500623-07:00',
      '2023-305T11',
      '2023-305T11,4',
      '2023-305T11.4',
      '2023-305T11:24',
      '2023-305T11:24,4',
      '2023-305T11:24.4',
      '2023-305T11:24:25',
      '2023-305T11:24:25.5',
      '2023-305T11:24:25.50',
      '2023-305T11:24:25,500',
      '2023-305T11:24:25.500',
      '2023-305T11:24:25,500623',
      '2023-305T11:24:25.500623',
      '2023-305T18Z',
      '2023-305T18,4Z',
      '2023-305T18.4Z',
      '2023-305T18:24Z',
      '2023-305T18:24,4Z',
      '2023-305T18:24.4Z',
      '2023-305T18:24:25Z',
      '2023-305T18:24:25.5Z',
      '2023-305T18:24:25.50Z',
      '2023-305T18:24:25,500Z',
      '2023-305T18:24:25.500Z',
      '2023-305T18:24:25,500623Z',
      '2023-305T18:24:25.500623Z',
      '2023-305T11-07',
      '2023-305T11,4-07',
      '2023-305T11.4-07',
      '2023-305T11:24-07',
      '2023-305T11:24,4-07',
      '2023-305T11:24.4-07',
      '2023-305T11:24:25-07',
      '2023-305T11:24:25.5-07',
      '2023-305T11:24:25.50-07',
      '2023-305T11:24:25,500-07',
      '2023-305T11:24:25.500-07',
      '2023-305T11:24:25,500623-07',
      '2023-305T11:24:25.500623-07',
      '2023-305T11-07:00',
      '2023-305T11,4-07:00',
      '2023-305T11.4-07:00',
      '2023-305T11:24-07:00',
      '2023-305T11:24,4-07:00',
      '2023-305T11:24.4-07:00',
      '2023-305T11:24:25-07:00',
      '2023-305T11:24:25.5-07:00',
      '2023-305T11:24:25.50-07:00',
      '2023-305T11:24:25,500-07:00',
      '2023-305T11:24:25.500-07:00',
      '2023-305T11:24:25,500623-07:00',
      '2023-305T11:24:25.500623-07:00',
      '20231101T11',
      '20231101T11,4',
      '20231101T11.4',
      '20231101T1124',
      '20231101T1124,4',
      '20231101T1124.4',
      '20231101T112425',
      '20231101T112425.5',
      '20231101T112425.50',
      '20231101T112425,500',
      '20231101T112425.500',
      '20231101T112425,500623',
      '20231101T112425.500623',
      '20231101T18Z',
      '20231101T18,4Z',
      '20231101T18.4Z',
      '20231101T1824Z',
      '20231101T1824,4Z',
      '20231101T1824.4Z',
      '20231101T182425Z',
      '20231101T182425.5Z',
      '20231101T182425.50Z',
      '20231101T182425,500Z',
      '20231101T182425.500Z',
      '20231101T182425,500623Z',
      '20231101T182425.500623Z',
      '20231101T11-07',
      '20231101T11,4-07',
      '20231101T11.4-07',
      '20231101T1124-07',
      '20231101T1124,4-07',
      '20231101T1124.4-07',
      '20231101T112425-07',
      '20231101T112425.5-07',
      '20231101T112425.50-07',
      '20231101T112425,500-07',
      '20231101T112425.500-07',
      '20231101T112425,500623-07',
      '20231101T112425.500623-07',
      '20231101T11-0700',
      '20231101T11,4-0700',
      '20231101T11.4-0700',
      '20231101T1124-0700',
      '20231101T1124,4-0700',
      '20231101T1124.4-0700',
      '20231101T112425-0700',
      '20231101T112425.5-0700',
      '20231101T112425.50-0700',
      '20231101T112425,500-0700',
      '20231101T112425.500-0700',
      '20231101T112425,500623-0700',
      '20231101T112425.500623-0700',
      '2023W443T11',
      '2023W443T11,4',
      '2023W443T11.4',
      '2023W443T1124',
      '2023W443T1124,4',
      '2023W443T1124.4',
      '2023W443T112425',
      '2023W443T112425.5',
      '2023W443T112425.50',
      '2023W443T112425,500',
      '2023W443T112425.500',
      '2023W443T112425,500623',
      '2023W443T112425.500623',
      '2023W443T18Z',
      '2023W443T18,4Z',
      '2023W443T18.4Z',
      '2023W443T1824Z',
      '2023W443T1824,4Z',
      '2023W443T1824.4Z',
      '2023W443T182425Z',
      '2023W443T182425.5Z',
      '2023W443T182425.50Z',
      '2023W443T182425,500Z',
      '2023W443T182425.500Z',
      '2023W443T182425,500623Z',
      '2023W443T182425.500623Z',
      '2023W443T11-07',
      '2023W443T11,4-07',
      '2023W443T11.4-07',
      '2023W443T1124-07',
      '2023W443T1124,4-07',
      '2023W443T1124.4-07',
      '2023W443T112425-07',
      '2023W443T112425.5-07',
      '2023W443T112425.50-07',
      '2023W443T112425,500-07',
      '2023W443T112425.500-07',
      '2023W443T112425,500623-07',
      '2023W443T112425.500623-07',
      '2023W443T11-0700',
      '2023W443T11,4-0700',
      '2023W443T11.4-0700',
      '2023W443T1124-0700',
      '2023W443T1124,4-0700',
      '2023W443T1124.4-0700',
      '2023W443T112425-0700',
      '2023W443T112425.5-0700',
      '2023W443T112425.50-0700',
      '2023W443T112425,500-0700',
      '2023W443T112425.500-0700',
      '2023W443T112425,500623-0700',
      '2023W443T112425.500623-0700',
      '2023305T11',
      '2023305T11,4',
      '2023305T11.4',
      '2023305T1124',
      '2023305T1124,4',
      '2023305T1124.4',
      '2023305T112425',
      '2023305T112425.5',
      '2023305T112425.50',
      '2023305T112425,500',
      '2023305T112425.500',
      '2023305T112425,500623',
      '2023305T112425.500623',
      '2023305T18Z',
      '2023305T18,4Z',
      '2023305T18.4Z',
      '2023305T1824Z',
      '2023305T1824,4Z',
      '2023305T1824.4Z',
      '2023305T182425Z',
      '2023305T182425.5Z',
      '2023305T182425.50Z',
      '2023305T182425,500Z',
      '2023305T182425.500Z',
      '2023305T182425,500623Z',
      '2023305T182425.500623Z',
      '2023305T11-07',
      '2023305T11,4-07',
      '2023305T11.4-07',
      '2023305T1124-07',
      '2023305T1124,4-07',
      '2023305T1124.4-07',
      '2023305T112425-07',
      '2023305T112425.5-07',
      '2023305T112425.50-07',
      '2023305T112425,500-07',
      '2023305T112425.500-07',
      '2023305T112425,500623-07',
      '2023305T112425.500623-07',
      '2023305T11-0700',
      '2023305T11,4-0700',
      '2023305T11.4-0700',
      '2023305T1124-0700',
      '2023305T1124,4-0700',
      '2023305T1124.4-0700',
      '2023305T112425-0700',
      '2023305T112425.5-0700',
      '2023305T112425.50-0700',
      '2023305T112425,500-0700',
      '2023305T112425.500-0700',
      '2023305T112425,500623-0700',
      '2023305T112425.500623-0700',
      '2023-11-02T02:24:25+08',
      '2023-11-01T06-12',
      '2023-11-01T06-12:00',
      '2023-11-01T06:24-12',
      '2023-11-01T06:24-12:00',
    ]

    rfc3339_dates.each do |date|
      assert(JSONSchemer.schema({ 'format' => 'date' }).valid?(date))
    end
    rfc3339_times.each do |time|
      assert(JSONSchemer.schema({ 'format' => 'time' }).valid?(time))
    end
    rfc3339_date_times.each do |date_time|
      assert(JSONSchemer.schema({ 'format' => 'date-time' }).valid?(date_time))
    end

    (iso8601_dates - rfc3339_dates).each do |date|
      refute(JSONSchemer.schema({ 'format' => 'date' }).valid?(date))
    end
    (iso8601_times - rfc3339_times).each do |time|
      refute(JSONSchemer.schema({ 'format' => 'time' }).valid?(time))
    end
    (iso8601_date_times - rfc3339_date_times).each do |date_time|
      refute(JSONSchemer.schema({ 'format' => 'date-time' }).valid?(date_time))
    end
  end

  def test_date_time_space_separator
    assert(JSONSchemer.schema({ 'format' => 'date-time' }).valid?('2023-11-01T23:00:00Z'))
    assert(JSONSchemer.schema({ 'format' => 'date-time' }).valid?('2023-11-01 23:00:00Z'))
    refute(JSONSchemer.schema({ 'format' => 'date-time' }).valid?('2023-11-01T24:00:00Z'))
    refute(JSONSchemer.schema({ 'format' => 'date-time' }).valid?('2023-11-01 24:00:00Z'))
    refute(JSONSchemer.schema({ 'format' => 'date-time' }).valid?('1998-12-31T23:58:60Z'))
    refute(JSONSchemer.schema({ 'format' => 'date-time' }).valid?('1998-12-31 23:58:60Z'))
  end
end
