// Code generated by go generate; DO NOT EDIT.
package openapi3_test

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/getkin/kin-openapi/openapi3"
)

func TestCallbackRef_Extensions(t *testing.T) {
	data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
	expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`)

	ref := openapi3.CallbackRef{}
	err := json.Unmarshal(data, &ref)
	assert.NoError(t, err)

	// captures extension
	assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
	assert.Equal(t, float64(1), ref.Extensions["x-order"])

	// does not capture non-extensions
	assert.Nil(t, ref.Extensions["something"])

	// validation
	err = ref.Validate(t.Context())
	require.EqualError(t, err, "extra sibling fields: [something]")

	err = ref.Validate(t.Context(), openapi3.ProhibitExtensionsWithRef())
	require.EqualError(t, err, "extra sibling fields: [something x-order]")

	err = ref.Validate(t.Context(), openapi3.AllowExtraSiblingFields("something"))
	assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined

	// Verify round trip JSON
	// Compare as string to make error message more readable if different
	outJson, err := ref.MarshalJSON()
	assert.NoError(t, err)
	assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data")

	// non-extension not json lookable
	_, err = ref.JSONLookup("something")
	assert.Error(t, err)

	t.Run("extentions in value", func(t *testing.T) {
		ref.Value = &openapi3.Callback{Extensions: map[string]any{}}
		ref.Value.Extensions["x-order"] = 2.0

		// prefers the value next to the \$ref over the one in the \$ref.
		v, err := ref.JSONLookup("x-order")
		assert.NoError(t, err)
		assert.Equal(t, float64(1), v)
	})
}

func TestExampleRef_Extensions(t *testing.T) {
	data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
	expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`)

	ref := openapi3.ExampleRef{}
	err := json.Unmarshal(data, &ref)
	assert.NoError(t, err)

	// captures extension
	assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
	assert.Equal(t, float64(1), ref.Extensions["x-order"])

	// does not capture non-extensions
	assert.Nil(t, ref.Extensions["something"])

	// validation
	err = ref.Validate(t.Context())
	require.EqualError(t, err, "extra sibling fields: [something]")

	err = ref.Validate(t.Context(), openapi3.ProhibitExtensionsWithRef())
	require.EqualError(t, err, "extra sibling fields: [something x-order]")

	err = ref.Validate(t.Context(), openapi3.AllowExtraSiblingFields("something"))
	assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined

	// Verify round trip JSON
	// Compare as string to make error message more readable if different
	outJson, err := ref.MarshalJSON()
	assert.NoError(t, err)
	assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data")

	// non-extension not json lookable
	_, err = ref.JSONLookup("something")
	assert.Error(t, err)

	t.Run("extentions in value", func(t *testing.T) {
		ref.Value = &openapi3.Example{Extensions: map[string]any{}}
		ref.Value.Extensions["x-order"] = 2.0

		// prefers the value next to the \$ref over the one in the \$ref.
		v, err := ref.JSONLookup("x-order")
		assert.NoError(t, err)
		assert.Equal(t, float64(1), v)
	})
}

func TestHeaderRef_Extensions(t *testing.T) {
	data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
	expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`)

	ref := openapi3.HeaderRef{}
	err := json.Unmarshal(data, &ref)
	assert.NoError(t, err)

	// captures extension
	assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
	assert.Equal(t, float64(1), ref.Extensions["x-order"])

	// does not capture non-extensions
	assert.Nil(t, ref.Extensions["something"])

	// validation
	err = ref.Validate(t.Context())
	require.EqualError(t, err, "extra sibling fields: [something]")

	err = ref.Validate(t.Context(), openapi3.ProhibitExtensionsWithRef())
	require.EqualError(t, err, "extra sibling fields: [something x-order]")

	err = ref.Validate(t.Context(), openapi3.AllowExtraSiblingFields("something"))
	assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined

	// Verify round trip JSON
	// Compare as string to make error message more readable if different
	outJson, err := ref.MarshalJSON()
	assert.NoError(t, err)
	assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data")

	// non-extension not json lookable
	_, err = ref.JSONLookup("something")
	assert.Error(t, err)

	// Header does not have its own extensions.
}

func TestLinkRef_Extensions(t *testing.T) {
	data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
	expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`)

	ref := openapi3.LinkRef{}
	err := json.Unmarshal(data, &ref)
	assert.NoError(t, err)

	// captures extension
	assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
	assert.Equal(t, float64(1), ref.Extensions["x-order"])

	// does not capture non-extensions
	assert.Nil(t, ref.Extensions["something"])

	// validation
	err = ref.Validate(t.Context())
	require.EqualError(t, err, "extra sibling fields: [something]")

	err = ref.Validate(t.Context(), openapi3.ProhibitExtensionsWithRef())
	require.EqualError(t, err, "extra sibling fields: [something x-order]")

	err = ref.Validate(t.Context(), openapi3.AllowExtraSiblingFields("something"))
	assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined

	// Verify round trip JSON
	// Compare as string to make error message more readable if different
	outJson, err := ref.MarshalJSON()
	assert.NoError(t, err)
	assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data")

	// non-extension not json lookable
	_, err = ref.JSONLookup("something")
	assert.Error(t, err)

	t.Run("extentions in value", func(t *testing.T) {
		ref.Value = &openapi3.Link{Extensions: map[string]any{}}
		ref.Value.Extensions["x-order"] = 2.0

		// prefers the value next to the \$ref over the one in the \$ref.
		v, err := ref.JSONLookup("x-order")
		assert.NoError(t, err)
		assert.Equal(t, float64(1), v)
	})
}

func TestParameterRef_Extensions(t *testing.T) {
	data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
	expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`)

	ref := openapi3.ParameterRef{}
	err := json.Unmarshal(data, &ref)
	assert.NoError(t, err)

	// captures extension
	assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
	assert.Equal(t, float64(1), ref.Extensions["x-order"])

	// does not capture non-extensions
	assert.Nil(t, ref.Extensions["something"])

	// validation
	err = ref.Validate(t.Context())
	require.EqualError(t, err, "extra sibling fields: [something]")

	err = ref.Validate(t.Context(), openapi3.ProhibitExtensionsWithRef())
	require.EqualError(t, err, "extra sibling fields: [something x-order]")

	err = ref.Validate(t.Context(), openapi3.AllowExtraSiblingFields("something"))
	assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined

	// Verify round trip JSON
	// Compare as string to make error message more readable if different
	outJson, err := ref.MarshalJSON()
	assert.NoError(t, err)
	assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data")

	// non-extension not json lookable
	_, err = ref.JSONLookup("something")
	assert.Error(t, err)

	t.Run("extentions in value", func(t *testing.T) {
		ref.Value = &openapi3.Parameter{Extensions: map[string]any{}}
		ref.Value.Extensions["x-order"] = 2.0

		// prefers the value next to the \$ref over the one in the \$ref.
		v, err := ref.JSONLookup("x-order")
		assert.NoError(t, err)
		assert.Equal(t, float64(1), v)
	})
}

func TestRequestBodyRef_Extensions(t *testing.T) {
	data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
	expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`)

	ref := openapi3.RequestBodyRef{}
	err := json.Unmarshal(data, &ref)
	assert.NoError(t, err)

	// captures extension
	assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
	assert.Equal(t, float64(1), ref.Extensions["x-order"])

	// does not capture non-extensions
	assert.Nil(t, ref.Extensions["something"])

	// validation
	err = ref.Validate(t.Context())
	require.EqualError(t, err, "extra sibling fields: [something]")

	err = ref.Validate(t.Context(), openapi3.ProhibitExtensionsWithRef())
	require.EqualError(t, err, "extra sibling fields: [something x-order]")

	err = ref.Validate(t.Context(), openapi3.AllowExtraSiblingFields("something"))
	assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined

	// Verify round trip JSON
	// Compare as string to make error message more readable if different
	outJson, err := ref.MarshalJSON()
	assert.NoError(t, err)
	assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data")

	// non-extension not json lookable
	_, err = ref.JSONLookup("something")
	assert.Error(t, err)

	t.Run("extentions in value", func(t *testing.T) {
		ref.Value = &openapi3.RequestBody{Extensions: map[string]any{}}
		ref.Value.Extensions["x-order"] = 2.0

		// prefers the value next to the \$ref over the one in the \$ref.
		v, err := ref.JSONLookup("x-order")
		assert.NoError(t, err)
		assert.Equal(t, float64(1), v)
	})
}

func TestResponseRef_Extensions(t *testing.T) {
	data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
	expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`)

	ref := openapi3.ResponseRef{}
	err := json.Unmarshal(data, &ref)
	assert.NoError(t, err)

	// captures extension
	assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
	assert.Equal(t, float64(1), ref.Extensions["x-order"])

	// does not capture non-extensions
	assert.Nil(t, ref.Extensions["something"])

	// validation
	err = ref.Validate(t.Context())
	require.EqualError(t, err, "extra sibling fields: [something]")

	err = ref.Validate(t.Context(), openapi3.ProhibitExtensionsWithRef())
	require.EqualError(t, err, "extra sibling fields: [something x-order]")

	err = ref.Validate(t.Context(), openapi3.AllowExtraSiblingFields("something"))
	assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined

	// Verify round trip JSON
	// Compare as string to make error message more readable if different
	outJson, err := ref.MarshalJSON()
	assert.NoError(t, err)
	assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data")

	// non-extension not json lookable
	_, err = ref.JSONLookup("something")
	assert.Error(t, err)

	t.Run("extentions in value", func(t *testing.T) {
		ref.Value = &openapi3.Response{Extensions: map[string]any{}}
		ref.Value.Extensions["x-order"] = 2.0

		// prefers the value next to the \$ref over the one in the \$ref.
		v, err := ref.JSONLookup("x-order")
		assert.NoError(t, err)
		assert.Equal(t, float64(1), v)
	})
}

func TestSchemaRef_Extensions(t *testing.T) {
	data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
	expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`)

	ref := openapi3.SchemaRef{}
	err := json.Unmarshal(data, &ref)
	assert.NoError(t, err)

	// captures extension
	assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
	assert.Equal(t, float64(1), ref.Extensions["x-order"])

	// does not capture non-extensions
	assert.Nil(t, ref.Extensions["something"])

	// validation
	err = ref.Validate(t.Context())
	require.EqualError(t, err, "extra sibling fields: [something]")

	err = ref.Validate(t.Context(), openapi3.ProhibitExtensionsWithRef())
	require.EqualError(t, err, "extra sibling fields: [something x-order]")

	err = ref.Validate(t.Context(), openapi3.AllowExtraSiblingFields("something"))
	assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined

	// Verify round trip JSON
	// Compare as string to make error message more readable if different
	outJson, err := ref.MarshalJSON()
	assert.NoError(t, err)
	assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data")

	// non-extension not json lookable
	_, err = ref.JSONLookup("something")
	assert.Error(t, err)

	t.Run("extentions in value", func(t *testing.T) {
		ref.Value = &openapi3.Schema{Extensions: map[string]any{}}
		ref.Value.Extensions["x-order"] = 2.0

		// prefers the value next to the \$ref over the one in the \$ref.
		v, err := ref.JSONLookup("x-order")
		assert.NoError(t, err)
		assert.Equal(t, float64(1), v)
	})
}

func TestSecuritySchemeRef_Extensions(t *testing.T) {
	data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`)
	expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`)

	ref := openapi3.SecuritySchemeRef{}
	err := json.Unmarshal(data, &ref)
	assert.NoError(t, err)

	// captures extension
	assert.Equal(t, "#/components/schemas/Pet", ref.Ref)
	assert.Equal(t, float64(1), ref.Extensions["x-order"])

	// does not capture non-extensions
	assert.Nil(t, ref.Extensions["something"])

	// validation
	err = ref.Validate(t.Context())
	require.EqualError(t, err, "extra sibling fields: [something]")

	err = ref.Validate(t.Context(), openapi3.ProhibitExtensionsWithRef())
	require.EqualError(t, err, "extra sibling fields: [something x-order]")

	err = ref.Validate(t.Context(), openapi3.AllowExtraSiblingFields("something"))
	assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined

	// Verify round trip JSON
	// Compare as string to make error message more readable if different
	outJson, err := ref.MarshalJSON()
	assert.NoError(t, err)
	assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data")

	// non-extension not json lookable
	_, err = ref.JSONLookup("something")
	assert.Error(t, err)

	t.Run("extentions in value", func(t *testing.T) {
		ref.Value = &openapi3.SecurityScheme{Extensions: map[string]any{}}
		ref.Value.Extensions["x-order"] = 2.0

		// prefers the value next to the \$ref over the one in the \$ref.
		v, err := ref.JSONLookup("x-order")
		assert.NoError(t, err)
		assert.Equal(t, float64(1), v)
	})
}
