2017-02-10 14:16:51 +00:00
defmodule JSON.LD.ContextTest do
use ExUnit.Case
2017-03-12 13:27:52 +00:00
alias RDF.NS . { XSD }
2017-02-10 14:16:51 +00:00
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 ==
2020-06-20 02:25:58 +00:00
" http://schema.org/ "
2017-02-10 14:16:51 +00:00
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
2020-06-20 02:25:58 +00:00
c = JSON.LD . context ( %{ " foo " = > %{ " @id " = > " http://example.com/ " , " @container " = > " @list " } } )
2017-02-10 14:16:51 +00:00
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
2020-06-20 02:25:58 +00:00
c = JSON.LD . context ( %{ " foo " = > %{ " @id " = > " http://example.com/ " , " @container " = > " @set " } } )
2017-02-10 14:16:51 +00:00
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
2020-06-20 02:25:58 +00:00
c = JSON.LD . context ( %{ " foo " = > %{ " @id " = > " http://example.com/ " , " @type " = > " @id " } } )
2017-02-10 14:16:51 +00:00
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
2020-06-20 02:25:58 +00:00
c =
JSON.LD . context ( %{
" foo " = > %{ " @id " = > " http://example.com/ " , " @type " = > to_string ( XSD . string ( ) ) }
} )
2017-02-10 14:16:51 +00:00
assert c . term_defs [ " foo " ]
assert c . term_defs [ " foo " ] . iri_mapping == " http://example.com/ "
2020-06-20 02:25:58 +00:00
assert c . term_defs [ " foo " ] . type_mapping == to_string ( XSD . string ( ) )
2017-02-10 14:16:51 +00:00
end
test " associates language mapping with predicate " do
2020-06-20 02:25:58 +00:00
c = JSON.LD . context ( %{ " foo " = > %{ " @id " = > " http://example.com/ " , " @language " = > " en " } } )
2017-02-10 14:16:51 +00:00
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 ( %{
2020-06-20 02:25:58 +00:00
" foo " = > " bar " ,
" bar " = > " baz " ,
" baz " = > " http://example.com/ "
} )
|> iri_mappings == %{
" foo " = > " http://example.com/ " ,
" bar " = > " http://example.com/ " ,
" baz " = > " http://example.com/ "
}
2017-02-10 14:16:51 +00:00
end
test " expands terms using @vocab " do
2020-06-20 02:25:58 +00:00
c =
JSON.LD . context ( %{
" foo " = > " bar " ,
" @vocab " = > " http://example.com/ "
} )
2017-02-10 14:16:51 +00:00
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 ( [
2020-06-20 02:25:58 +00:00
%{ " foo " = > " http://example.com/foo " } ,
%{ " bar " = > " foo " }
] )
|> iri_mappings == %{
" foo " = > " http://example.com/foo " ,
" bar " = > " http://example.com/foo "
}
2017-02-10 14:16:51 +00:00
end
end
describe " term definitions with null values " do
test " removes @language if set to null " do
assert JSON.LD . context ( [
2020-06-20 02:25:58 +00:00
%{ " @language " = > " en " } ,
%{ " @language " = > nil }
] ) . default_language == nil
2017-02-10 14:16:51 +00:00
end
test " removes @vocab if set to null " do
assert JSON.LD . context ( [
2020-06-20 02:25:58 +00:00
%{ " @vocab " = > " http://schema.org/ " } ,
%{ " @vocab " = > nil }
] ) . vocab == nil
2017-02-10 14:16:51 +00:00
end
test " removes term if set to null with @vocab " do
2020-06-20 02:25:58 +00:00
assert JSON.LD . context ( [
%{
" @vocab " = > " http://schema.org/ " ,
" term " = > nil
}
] )
|> iri_mappings == %{
" term " = > nil
}
2017-02-10 14:16:51 +00:00
end
test " removes a term definition " do
assert JSON.LD . context ( %{ " name " = > nil } ) . term_defs [ " name " ] == nil
end
test " loads initial context " do
2020-06-20 02:25:58 +00:00
init_ec = JSON.LD.Context . new ( )
2017-02-10 14:16:51 +00:00
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
2021-08-19 13:43:59 +00:00
describe " remote contexts " do
test " when the remote context is a list " do
2021-08-19 20:29:57 +00:00
bypass = Bypass . open ( )
Bypass . expect ( bypass , fn conn ->
assert " GET " == conn . method
assert " /litepub-0.1.jsonld " == conn . request_path
context = File . read! ( " test/fixtures/litepub-0.1.jsonld " )
Plug.Conn . resp ( conn , 200 , context )
end )
assert context = JSON.LD . context ( " http://localhost: #{ bypass . port } /litepub-0.1.jsonld " )
2021-08-19 14:00:09 +00:00
2021-08-19 13:43:59 +00:00
assert %{
" Emoji " = > " http://joinmastodon.org/ns # Emoji " ,
# https://www.w3.org/ns/activitystreams
" Accept " = > " https://www.w3.org/ns/activitystreams # Accept " ,
# https://w3id.org/security/v1
" CryptographicKey " = > " https://w3id.org/security # Key "
} = iri_mappings ( context )
end
end
2022-04-22 00:47:44 +00:00
describe " JSON.LD.context/2 " do
@example_context_map %{
" @context " = > %{
" givenName " = > " http://schema.org/givenName " ,
" familyName " = > " http://schema.org/familyName " ,
" homepage " = > %{
" @id " = > " http://schema.org/url " ,
" @type " = > " @id "
}
}
}
test " wraps everything under a @context " do
assert JSON.LD . context ( @example_context_map [ " @context " ] ) ==
JSON.LD . context ( @example_context_map )
end
test " with atom keys " do
context_with_atom_keys = %{
givenName : " http://schema.org/givenName " ,
familyName : " http://schema.org/familyName " ,
homepage : %{
" @id " : " http://schema.org/url " ,
" @type " : " @id "
}
}
assert JSON.LD . context ( context_with_atom_keys ) ==
JSON.LD . context ( @example_context_map )
assert JSON.LD . context ( %{ " @context " : context_with_atom_keys } ) ==
JSON.LD . context ( @example_context_map )
assert JSON.LD . context ( %{ " @context " = > context_with_atom_keys } ) ==
JSON.LD . context ( @example_context_map )
end
2022-04-22 20:25:24 +00:00
test " with a RDF.PropertyMap " do
expected_context = %{
" @context " = > %{
" givenName " = > " http://schema.org/givenName " ,
" familyName " = > " http://schema.org/familyName "
}
}
property_map =
RDF . property_map (
givenName : " http://schema.org/givenName " ,
familyName : " http://schema.org/familyName "
)
assert JSON.LD . context ( property_map ) == JSON.LD . context ( expected_context )
end
2022-04-22 00:47:44 +00:00
end
2017-02-10 14:16:51 +00:00
describe " errors " do
%{
" no @id, @type, or @container " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ } } ,
exception : JSON.LD.InvalidIRIMappingError
} ,
2017-02-10 14:16:51 +00:00
" value as array " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > [ ] } ,
exception : JSON.LD.InvalidTermDefinitionError
} ,
2017-02-10 14:16:51 +00:00
" @id as object " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @id " = > %{ } } } ,
exception : JSON.LD.InvalidIRIMappingError
} ,
2017-02-10 14:16:51 +00:00
" @id as array of object " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @id " = > [ { } ] } } ,
exception : JSON.LD.InvalidIRIMappingError
} ,
2017-02-10 14:16:51 +00:00
" @id as array of null " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @id " = > [ nil ] } } ,
exception : JSON.LD.InvalidIRIMappingError
} ,
2017-02-10 14:16:51 +00:00
" @type as object " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @type " = > %{ } } } ,
exception : JSON.LD.InvalidTypeMappingError
} ,
2017-02-10 14:16:51 +00:00
" @type as array " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @type " = > [ ] } } ,
exception : JSON.LD.InvalidTypeMappingError
} ,
2017-02-10 14:16:51 +00:00
" @type as @list " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @type " = > " @list " } } ,
exception : JSON.LD.InvalidTypeMappingError
} ,
2017-02-10 14:16:51 +00:00
" @type as @set " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @type " = > " @set " } } ,
exception : JSON.LD.InvalidTypeMappingError
} ,
2017-02-10 14:16:51 +00:00
" @container as object " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @container " = > %{ } } } ,
exception : JSON.LD.InvalidIRIMappingError
} ,
2017-02-10 14:16:51 +00:00
" @container as array " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @container " = > [ ] } } ,
exception : JSON.LD.InvalidIRIMappingError
} ,
2017-02-10 14:16:51 +00:00
" @container as string " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " foo " = > %{ " @container " = > " true " } } ,
exception : JSON.LD.InvalidIRIMappingError
} ,
2017-02-10 14:16:51 +00:00
" @language as @id " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " @language " = > %{ " @id " = > " http://example.com/ " } } ,
exception : JSON.LD.InvalidDefaultLanguageError
} ,
2017-02-10 14:16:51 +00:00
" @vocab as @id " = > %{
2020-06-20 02:25:58 +00:00
input : %{ " @vocab " = > %{ " @id " = > " http://example.com/ " } } ,
exception : JSON.LD.InvalidVocabMappingError
}
2017-02-10 14:16:51 +00:00
}
2020-06-20 02:25:58 +00:00
|> 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 )
2017-02-10 14:16:51 +00:00
2020-06-20 02:25:58 +00:00
( JSON.LD . keywords ( ) -- ~w[ @base @language @vocab ] )
2017-02-10 14:16:51 +00:00
|> Enum . each ( fn keyword ->
2020-06-20 02:25:58 +00:00
@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
2017-02-10 14:16:51 +00:00
2020-06-20 02:25:58 +00:00
@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 )
2017-02-10 14:16:51 +00:00
end
2017-06-25 00:07:21 +00:00
# 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
2017-02-10 14:16:51 +00:00
@tag :skip
test " an empty string is not a valid term "
2017-06-25 00:07:21 +00:00
# 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
2017-02-10 14:16:51 +00:00
@tag :skip
test " warn on terms starting with a @ "
def iri_mappings ( % JSON.LD.Context { term_defs : term_defs } ) do
2020-06-20 02:25:58 +00:00
Enum . reduce ( term_defs , %{ } , fn { term , term_def } , iri_mappings ->
Map . put ( iri_mappings , term , ( term_def && term_def . iri_mapping ) || nil )
end )
2017-02-10 14:16:51 +00:00
end
def languages ( % JSON.LD.Context { term_defs : term_defs } ) do
2020-06-20 02:25:58 +00:00
Enum . reduce ( term_defs , %{ } , fn { term , term_def } , language_mappings ->
Map . put ( language_mappings , term , term_def . language_mapping )
end )
2017-02-10 14:16:51 +00:00
end
def coercions ( % JSON.LD.Context { term_defs : term_defs } ) do
2020-06-20 02:25:58 +00:00
Enum . reduce ( term_defs , %{ } , fn { term , term_def } , type_mappings ->
Map . put ( type_mappings , term , term_def . type_mapping )
end )
2017-02-10 14:16:51 +00:00
end
def containers ( % JSON.LD.Context { term_defs : term_defs } ) do
2020-06-20 02:25:58 +00:00
Enum . reduce ( term_defs , %{ } , fn { term , term_def } , type_mappings ->
Map . put ( type_mappings , term , term_def . container_mapping )
end )
2017-02-10 14:16:51 +00:00
end
end