jsonld-ex/test/unit/context_test.exs
2017-06-25 02:07:21 +02:00

265 lines
9 KiB
Elixir

defmodule JSON.LD.ContextTest do
use ExUnit.Case
alias RDF.NS.{XSD}
doctest JSON.LD.Context
describe "create from Hash" do
test "extracts @base" do
assert JSON.LD.context(%{"@base" => "http://base/"}).base_iri == "http://base/"
end
test "extracts @language" do
assert JSON.LD.context(%{"@language" => "en"}).default_language == "en"
end
test "extracts @vocab" do
assert JSON.LD.context(%{"@vocab" => "http://schema.org/"}).vocab ==
"http://schema.org/"
end
test "maps term with IRI value" do
c = JSON.LD.context(%{"foo" => "http://example.com/"})
assert c.term_defs["foo"]
assert c.term_defs["foo"].iri_mapping == "http://example.com/"
end
test "maps term with @id" do
c = JSON.LD.context(%{"foo" => %{"@id" => "http://example.com/"}})
assert c.term_defs["foo"]
assert c.term_defs["foo"].iri_mapping == "http://example.com/"
end
test "associates @list container mapping with predicate" do
c = JSON.LD.context(%{"foo" =>
%{"@id" => "http://example.com/", "@container" => "@list"}})
assert c.term_defs["foo"]
assert c.term_defs["foo"].iri_mapping == "http://example.com/"
assert c.term_defs["foo"].container_mapping == "@list"
end
test "associates @set container mapping with predicate" do
c = JSON.LD.context(%{"foo" =>
%{"@id" => "http://example.com/", "@container" => "@set"}})
assert c.term_defs["foo"]
assert c.term_defs["foo"].iri_mapping == "http://example.com/"
assert c.term_defs["foo"].container_mapping == "@set"
end
test "associates @id container mapping with predicate" do
c = JSON.LD.context(%{"foo" =>
%{"@id" => "http://example.com/", "@type" => "@id"}})
assert c.term_defs["foo"]
assert c.term_defs["foo"].iri_mapping == "http://example.com/"
assert c.term_defs["foo"].type_mapping == "@id"
end
test "associates type mapping with predicate" do
c = JSON.LD.context(%{"foo" =>
%{"@id" => "http://example.com/", "@type" => to_string(XSD.string)}})
assert c.term_defs["foo"]
assert c.term_defs["foo"].iri_mapping == "http://example.com/"
assert c.term_defs["foo"].type_mapping == to_string(XSD.string)
end
test "associates language mapping with predicate" do
c = JSON.LD.context(%{"foo" =>
%{"@id" => "http://example.com/", "@language" => "en"}})
assert c.term_defs["foo"]
assert c.term_defs["foo"].iri_mapping == "http://example.com/"
assert c.term_defs["foo"].language_mapping == "en"
end
test "expands chains of term definition/use with string values" do
assert JSON.LD.context(%{
"foo" => "bar",
"bar" => "baz",
"baz" => "http://example.com/"
}) |> iri_mappings == %{
"foo" => "http://example.com/",
"bar" => "http://example.com/",
"baz" => "http://example.com/"
}
end
test "expands terms using @vocab" do
c = JSON.LD.context(%{
"foo" => "bar",
"@vocab" => "http://example.com/"})
assert c.term_defs["foo"]
assert c.term_defs["foo"].iri_mapping == "http://example.com/bar"
end
end
describe "create from Array/List" do
test "merges definitions from each context" do
assert JSON.LD.context([
%{"foo" => "http://example.com/foo"},
%{"bar" => "foo"}
]) |> iri_mappings == %{
"foo" => "http://example.com/foo",
"bar" => "http://example.com/foo"
}
end
end
describe "term definitions with null values" do
test "removes @language if set to null" do
assert JSON.LD.context([
%{ "@language" => "en" },
%{ "@language" => nil }
]).default_language == nil
end
test "removes @vocab if set to null" do
assert JSON.LD.context([
%{ "@vocab" => "http://schema.org/" },
%{ "@vocab" => nil }
]).vocab == nil
end
test "removes term if set to null with @vocab" do
assert JSON.LD.context([%{
"@vocab" => "http://schema.org/",
"term" => nil
}]) |> iri_mappings == %{
"term" => nil
}
end
test "removes a term definition" do
assert JSON.LD.context(%{"name" => nil}).term_defs["name"] == nil
end
test "loads initial context" do
init_ec = JSON.LD.Context.new
nil_ec = JSON.LD.context(nil)
assert nil_ec.default_language == init_ec.default_language
assert nil_ec |> coercions == init_ec |> coercions
assert nil_ec |> containers == init_ec |> containers
assert nil_ec |> languages == init_ec |> languages
assert nil_ec |> iri_mappings == init_ec |> iri_mappings
end
end
describe "errors" do
%{
"no @id, @type, or @container" => %{
input: %{"foo" => %{}},
exception: JSON.LD.InvalidIRIMappingError
},
"value as array" => %{
input: %{"foo" => []},
exception: JSON.LD.InvalidTermDefinitionError
},
"@id as object" => %{
input: %{"foo" => %{"@id" => %{}}},
exception: JSON.LD.InvalidIRIMappingError
},
"@id as array of object" => %{
input: %{"foo" => %{"@id" => [{}]}},
exception: JSON.LD.InvalidIRIMappingError
},
"@id as array of null" => %{
input: %{"foo" => %{"@id" => [nil]}},
exception: JSON.LD.InvalidIRIMappingError
},
"@type as object" => %{
input: %{"foo" => %{"@type" => %{}}},
exception: JSON.LD.InvalidTypeMappingError
},
"@type as array" => %{
input: %{"foo" => %{"@type" => []}},
exception: JSON.LD.InvalidTypeMappingError
},
"@type as @list" => %{
input: %{"foo" => %{"@type" => "@list"}},
exception: JSON.LD.InvalidTypeMappingError
},
"@type as @set" => %{
input: %{"foo" => %{"@type" => "@set"}},
exception: JSON.LD.InvalidTypeMappingError
},
"@container as object" => %{
input: %{"foo" => %{"@container" => %{}}},
exception: JSON.LD.InvalidIRIMappingError
},
"@container as array" => %{
input: %{"foo" => %{"@container" => []}},
exception: JSON.LD.InvalidIRIMappingError
},
"@container as string" => %{
input: %{"foo" => %{"@container" => "true"}},
exception: JSON.LD.InvalidIRIMappingError
},
"@language as @id" => %{
input: %{"@language" => %{"@id" => "http://example.com/"}},
exception: JSON.LD.InvalidDefaultLanguageError
},
"@vocab as @id" => %{
input: %{"@vocab" => %{"@id" => "http://example.com/"}},
exception: JSON.LD.InvalidVocabMappingError
},
}
|> Enum.each(fn ({title, data}) ->
@tag data: data
test title, %{data: data} do
assert_raise data.exception, fn ->
JSON.LD.context(data.input)
end
end
end)
(JSON.LD.keywords -- ~w[@base @language @vocab])
|> Enum.each(fn keyword ->
@tag keyword: keyword
test "does not redefine #{keyword} as a string", %{keyword: keyword} do
assert_raise JSON.LD.KeywordRedefinitionError, fn ->
JSON.LD.context(%{"@context" => %{keyword => "http://example.com/"}})
end
end
@tag keyword: keyword
test "does not redefine #{keyword} with an @id", %{keyword: keyword} do
assert_raise JSON.LD.KeywordRedefinitionError, fn ->
JSON.LD.context(%{"@context" => %{keyword => %{"@id" => "http://example.com/"}}})
end
end
end)
end
# TODO: "Furthermore, the term must not be an empty string ("") as not all programming languages are able to handle empty JSON keys." -- https://www.w3.org/TR/json-ld/#terms
@tag :skip
test "an empty string is not a valid term"
# TODO: "To avoid forward-compatibility issues, a term should not start with an @ character as future versions of JSON-LD may introduce additional keywords." -- https://www.w3.org/TR/json-ld/#terms
@tag :skip
test "warn on terms starting with a @"
def iri_mappings(%JSON.LD.Context{term_defs: term_defs}) do
Enum.reduce term_defs, %{}, fn ({term, term_def}, iri_mappings) ->
Map.put iri_mappings, term, (term_def && term_def.iri_mapping) || nil
end
end
def languages(%JSON.LD.Context{term_defs: term_defs}) do
Enum.reduce term_defs, %{}, fn ({term, term_def}, language_mappings) ->
Map.put language_mappings, term, term_def.language_mapping
end
end
def coercions(%JSON.LD.Context{term_defs: term_defs}) do
Enum.reduce term_defs, %{}, fn ({term, term_def}, type_mappings) ->
Map.put type_mappings, term, term_def.type_mapping
end
end
def containers(%JSON.LD.Context{term_defs: term_defs}) do
Enum.reduce term_defs, %{}, fn ({term, term_def}, type_mappings) ->
Map.put type_mappings, term, term_def.container_mapping
end
end
end