668 lines
22 KiB
Elixir
668 lines
22 KiB
Elixir
defmodule JSON.LD.DecoderTest do
|
|
use ExUnit.Case, async: false
|
|
|
|
doctest JSON.LD.Decoder
|
|
|
|
alias RDF.Dataset
|
|
alias RDF.NS
|
|
alias RDF.NS.{XSD, RDFS}
|
|
|
|
import RDF.Sigils
|
|
|
|
defmodule TestNS do
|
|
use RDF.Vocabulary.Namespace
|
|
defvocab EX, base_iri: "http://example.org/#", terms: [], strict: false
|
|
defvocab S, base_iri: "http://schema.org/", terms: [], strict: false
|
|
end
|
|
|
|
alias TestNS.{EX, S}
|
|
|
|
|
|
test "an empty JSON document is deserialized to an empty graph" do
|
|
assert JSON.LD.Decoder.decode!("{}") == Dataset.new
|
|
end
|
|
|
|
describe "unnamed nodes" do
|
|
%{
|
|
"no @id" => {
|
|
~s({
|
|
"http://example.com/foo": "bar"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, RDF.literal("bar")}
|
|
},
|
|
"@id with _:a" => {
|
|
~s({
|
|
"@id": "_:a",
|
|
"http://example.com/foo": "bar"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, RDF.literal("bar")}
|
|
},
|
|
"@id with _:a and reference" => {
|
|
~s({
|
|
"@id": "_:a",
|
|
"http://example.com/foo": {"@id": "_:a"}
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, RDF.bnode("b0")}
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "nodes with @id" do
|
|
%{
|
|
"with IRI" => {
|
|
~s({
|
|
"@id": "http://example.com/a",
|
|
"http://example.com/foo": "bar"
|
|
}),
|
|
{~I<http://example.com/a>, ~I<http://example.com/foo>, RDF.literal("bar")}
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
|
|
%{
|
|
"base" => {
|
|
~s({
|
|
"@id": "",
|
|
"@type": "#{RDF.uri(RDFS.Resource)}"
|
|
}),
|
|
{~I<http://example.org/>, NS.RDF.type, RDF.uri(RDFS.Resource)}
|
|
},
|
|
"relative" => {
|
|
~s({
|
|
"@id": "a/b",
|
|
"@type": "#{RDF.uri(RDFS.Resource)}"
|
|
}),
|
|
{~I<http://example.org/a/b>, NS.RDF.type, RDF.uri(RDFS.Resource)}
|
|
},
|
|
"hash" => {
|
|
~s({
|
|
"@id": "#a",
|
|
"@type": "#{RDF.uri(RDFS.Resource)}"
|
|
}),
|
|
{~I<http://example.org/#a>, NS.RDF.type, RDF.uri(RDFS.Resource)}
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test "when relative IRIs #{title}", %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input, base: "http://example.org/") ==
|
|
RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "typed nodes" do
|
|
%{
|
|
"one type" => {
|
|
~s({
|
|
"@type": "http://example.com/foo"
|
|
}),
|
|
{RDF.bnode("b0"), NS.RDF.type, ~I<http://example.com/foo>}
|
|
},
|
|
"two types" => {
|
|
~s({
|
|
"@type": ["http://example.com/foo", "http://example.com/baz"]
|
|
}),
|
|
[
|
|
{RDF.bnode("b0"), NS.RDF.type, ~I<http://example.com/foo>},
|
|
{RDF.bnode("b0"), NS.RDF.type, ~I<http://example.com/baz>},
|
|
]
|
|
},
|
|
"blank node type" => {
|
|
~s({
|
|
"@type": "_:foo"
|
|
}),
|
|
{RDF.bnode("b1"), NS.RDF.type, RDF.bnode("b0")}
|
|
}
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "key/value" do
|
|
%{
|
|
"string" => {
|
|
~s({
|
|
"http://example.com/foo": "bar"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, RDF.literal("bar")}
|
|
},
|
|
"strings" => {
|
|
~s({
|
|
"http://example.com/foo": ["bar", "baz"]
|
|
}),
|
|
[
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, RDF.literal("bar")},
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, RDF.literal("baz")},
|
|
]
|
|
},
|
|
"IRI" => {
|
|
~s({
|
|
"http://example.com/foo": {"@id": "http://example.com/bar"}
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, ~I<http://example.com/bar>}
|
|
},
|
|
"IRIs" => {
|
|
~s({
|
|
"http://example.com/foo": [{"@id": "http://example.com/bar"}, {"@id": "http://example.com/baz"}]
|
|
}),
|
|
[
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, ~I<http://example.com/bar>},
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, ~I<http://example.com/baz>},
|
|
]
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "literals" do
|
|
%{
|
|
"plain literal" =>
|
|
{
|
|
~s({"@id": "http://greggkellogg.net/foaf#me", "http://xmlns.com/foaf/0.1/name": "Gregg Kellogg"}),
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/name>, RDF.literal("Gregg Kellogg")},
|
|
},
|
|
"explicit plain literal" =>
|
|
{
|
|
~s({"http://xmlns.com/foaf/0.1/name": {"@value": "Gregg Kellogg"}}),
|
|
{RDF.bnode("b0"), ~I<http://xmlns.com/foaf/0.1/name>, RDF.literal("Gregg Kellogg")}
|
|
},
|
|
"language tagged literal" =>
|
|
{
|
|
~s({"http://www.w3.org/2000/01/rdf-schema#label": {"@value": "A plain literal with a lang tag.", "@language": "en-us"}}),
|
|
{RDF.bnode("b0"), RDFS.label, RDF.literal("A plain literal with a lang tag.", language: "en-us")}
|
|
},
|
|
"I18N literal with language" =>
|
|
{
|
|
~s([{
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"http://xmlns.com/foaf/0.1/knows": {"@id": "http://www.ivan-herman.net/foaf#me"}
|
|
},{
|
|
"@id": "http://www.ivan-herman.net/foaf#me",
|
|
"http://xmlns.com/foaf/0.1/name": {"@value": "Herman Iván", "@language": "hu"}
|
|
}]),
|
|
[
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, ~I<http://www.ivan-herman.net/foaf#me>},
|
|
{~I<http://www.ivan-herman.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/name>, RDF.literal("Herman Iv\u00E1n", language: "hu")},
|
|
]
|
|
},
|
|
"explicit datatyped literal" =>
|
|
{
|
|
~s({
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"http://purl.org/dc/terms/created": {"@value": "1957-02-27", "@type": "http://www.w3.org/2001/XMLSchema#date"}
|
|
}),
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://purl.org/dc/terms/created>, RDF.literal("1957-02-27", datatype: XSD.date)},
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "prefixes" do
|
|
%{
|
|
"empty prefix" => {
|
|
~s({"@context": {"": "http://example.com/default#"}, ":foo": "bar"}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/default#foo>, RDF.literal("bar")}
|
|
},
|
|
# TODO:
|
|
"empty suffix" => {
|
|
~s({"@context": {"prefix": "http://example.com/default#"}, "prefix:": "bar"}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/default#>, RDF.literal("bar")}
|
|
},
|
|
"prefix:suffix" => {
|
|
~s({"@context": {"prefix": "http://example.com/default#"}, "prefix:foo": "bar"}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/default#foo>, RDF.literal("bar")}
|
|
}
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
if title == "empty suffix", do: @tag :skip
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "overriding keywords" do
|
|
%{
|
|
"'url' for @id, 'a' for @type" => {
|
|
~s({
|
|
"@context": {"url": "@id", "a": "@type", "name": "http://schema.org/name"},
|
|
"url": "http://example.com/about#gregg",
|
|
"a": "http://schema.org/Person",
|
|
"name": "Gregg Kellogg"
|
|
}),
|
|
[
|
|
{~I<http://example.com/about#gregg>, NS.RDF.type, ~I<http://schema.org/Person>},
|
|
{~I<http://example.com/about#gregg>, ~I<http://schema.org/name>, RDF.literal("Gregg Kellogg")},
|
|
]
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "chaining" do
|
|
%{
|
|
"explicit subject" =>
|
|
{
|
|
~s({
|
|
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"foaf:knows": {
|
|
"@id": "http://www.ivan-herman.net/foaf#me",
|
|
"foaf:name": "Ivan Herman"
|
|
}
|
|
}),
|
|
[
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, ~I<http://www.ivan-herman.net/foaf#me>},
|
|
{~I<http://www.ivan-herman.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/name>, RDF.literal("Ivan Herman")},
|
|
]
|
|
},
|
|
"implicit subject" =>
|
|
{
|
|
~s({
|
|
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"foaf:knows": {
|
|
"foaf:name": "Manu Sporny"
|
|
}
|
|
}),
|
|
[
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, RDF.bnode("b0")},
|
|
{RDF.bnode("b0"), ~I<http://xmlns.com/foaf/0.1/name>, RDF.literal("Manu Sporny")},
|
|
]
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "multiple values" do
|
|
%{
|
|
"literals" =>
|
|
{
|
|
~s({
|
|
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"foaf:knows": ["Manu Sporny", "Ivan Herman"]
|
|
}),
|
|
[
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, RDF.literal("Manu Sporny")},
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, RDF.literal("Ivan Herman")},
|
|
]
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "lists" do
|
|
%{
|
|
"Empty" => {
|
|
~s({
|
|
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"foaf:knows": {"@list": []}
|
|
}),
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, NS.RDF.nil}
|
|
},
|
|
"single value" => {
|
|
~s({
|
|
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"foaf:knows": {"@list": ["Manu Sporny"]}
|
|
}),
|
|
[
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, RDF.bnode("b0")},
|
|
{RDF.bnode("b0"), NS.RDF.first, RDF.literal("Manu Sporny")},
|
|
{RDF.bnode("b0"), NS.RDF.rest, NS.RDF.nil},
|
|
]
|
|
},
|
|
"single value (with coercion)" => {
|
|
~s({
|
|
"@context": {
|
|
"foaf": "http://xmlns.com/foaf/0.1/",
|
|
"foaf:knows": { "@container": "@list"}
|
|
},
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"foaf:knows": ["Manu Sporny"]
|
|
}),
|
|
[
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, RDF.bnode("b0")},
|
|
{RDF.bnode("b0"), NS.RDF.first, RDF.literal("Manu Sporny")},
|
|
{RDF.bnode("b0"), NS.RDF.rest, NS.RDF.nil},
|
|
]
|
|
},
|
|
"multiple values" => {
|
|
~s({
|
|
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"foaf:knows": {"@list": ["Manu Sporny", "Dave Longley"]}
|
|
}),
|
|
[
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, RDF.bnode("b0")},
|
|
{RDF.bnode("b0"), NS.RDF.first, RDF.literal("Manu Sporny")},
|
|
{RDF.bnode("b0"), NS.RDF.rest, RDF.bnode("b1")},
|
|
{RDF.bnode("b1"), NS.RDF.first, RDF.literal("Dave Longley")},
|
|
{RDF.bnode("b1"), NS.RDF.rest, NS.RDF.nil},
|
|
]
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "context" do
|
|
%{
|
|
"@id coersion" =>
|
|
{
|
|
~s({
|
|
"@context": {
|
|
"knows": {"@id": "http://xmlns.com/foaf/0.1/knows", "@type": "@id"}
|
|
},
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"knows": "http://www.ivan-herman.net/foaf#me"
|
|
}),
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://xmlns.com/foaf/0.1/knows>, ~I<http://www.ivan-herman.net/foaf#me>},
|
|
},
|
|
"datatype coersion" =>
|
|
{
|
|
~s({
|
|
"@context": {
|
|
"dcterms": "http://purl.org/dc/terms/",
|
|
"xsd": "http://www.w3.org/2001/XMLSchema#",
|
|
"created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:date"}
|
|
},
|
|
"@id": "http://greggkellogg.net/foaf#me",
|
|
"created": "1957-02-27"
|
|
}),
|
|
{~I<http://greggkellogg.net/foaf#me>, ~I<http://purl.org/dc/terms/created>, RDF.literal("1957-02-27", datatype: XSD.date)},
|
|
},
|
|
"sub-objects with context" => {
|
|
~s({
|
|
"@context": {"foo": "http://example.com/foo"},
|
|
"foo": {
|
|
"@context": {"foo": "http://example.org/foo"},
|
|
"foo": "bar"
|
|
}
|
|
}),
|
|
[
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, RDF.bnode("b1")},
|
|
{RDF.bnode("b1"), ~I<http://example.org/foo>, RDF.literal("bar")},
|
|
]
|
|
},
|
|
"contexts with a list processed in order" => {
|
|
~s({
|
|
"@context": [
|
|
{"foo": "http://example.com/foo"},
|
|
{"foo": "http://example.org/foo"}
|
|
],
|
|
"foo": "bar"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.org/foo>, RDF.literal("bar")},
|
|
},
|
|
"term definition resolves term as IRI" => {
|
|
~s({
|
|
"@context": [
|
|
{"foo": "http://example.com/foo"},
|
|
{"bar": "foo"}
|
|
],
|
|
"bar": "bar"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo>, RDF.literal("bar")},
|
|
},
|
|
"term definition resolves prefix as IRI" => {
|
|
~s({
|
|
"@context": [
|
|
{"foo": "http://example.com/foo#"},
|
|
{"bar": "foo:bar"}
|
|
],
|
|
"bar": "bar"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo#bar>, RDF.literal("bar")},
|
|
},
|
|
"@language" => {
|
|
~s({
|
|
"@context": {
|
|
"foo": "http://example.com/foo#",
|
|
"@language": "en"
|
|
},
|
|
"foo:bar": "baz"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo#bar>, RDF.literal("baz", language: "en")},
|
|
},
|
|
"@language with override" => {
|
|
~s({
|
|
"@context": {
|
|
"foo": "http://example.com/foo#",
|
|
"@language": "en"
|
|
},
|
|
"foo:bar": {"@value": "baz", "@language": "fr"}
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo#bar>, RDF.literal("baz", language: "fr")},
|
|
},
|
|
"@language with plain" => {
|
|
~s({
|
|
"@context": {
|
|
"foo": "http://example.com/foo#",
|
|
"@language": "en"
|
|
},
|
|
"foo:bar": {"@value": "baz"}
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.com/foo#bar>, RDF.literal("baz")},
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
|
|
%{
|
|
"dt with term" => {
|
|
~s({
|
|
"@context": [
|
|
{"date": "http://www.w3.org/2001/XMLSchema#date", "term": "http://example.org/foo#"},
|
|
{"foo": {"@id": "term", "@type": "date"}}
|
|
],
|
|
"foo": "bar"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.org/foo#>, RDF.literal("bar", datatype: XSD.date)},
|
|
},
|
|
"@id with term" => {
|
|
~s({
|
|
"@context": [
|
|
{"foo": {"@id": "http://example.org/foo#bar", "@type": "@id"}}
|
|
],
|
|
"foo": "http://example.org/foo#bar"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://example.org/foo#bar>, ~I<http://example.org/foo#bar>},
|
|
},
|
|
"coercion without term definition" => {
|
|
~s({
|
|
"@context": [
|
|
{
|
|
"xsd": "http://www.w3.org/2001/XMLSchema#",
|
|
"dc": "http://purl.org/dc/terms/"
|
|
},
|
|
{
|
|
"dc:date": {"@type": "xsd:date"}
|
|
}
|
|
],
|
|
"dc:date": "2011-11-23"
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://purl.org/dc/terms/date>, RDF.literal("2011-11-23", datatype: XSD.date)},
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test "term def with @id + @type coercion: #{title}", %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
|
|
%{
|
|
"dt with term" => {
|
|
~s({
|
|
"@context": [
|
|
{"date": "http://www.w3.org/2001/XMLSchema#date", "term": "http://example.org/foo#"},
|
|
{"foo": {"@id": "term", "@type": "date", "@container": "@list"}}
|
|
],
|
|
"foo": ["bar"]
|
|
}),
|
|
[
|
|
{RDF.bnode("b0"), ~I<http://example.org/foo#>, RDF.bnode("b1")},
|
|
{RDF.bnode("b1"), NS.RDF.first, RDF.literal("bar", datatype: XSD.date)},
|
|
{RDF.bnode("b1"), NS.RDF.rest, NS.RDF.nil},
|
|
]
|
|
},
|
|
"@id with term" => {
|
|
~s({
|
|
"@context": [
|
|
{"foo": {"@id": "http://example.org/foo#bar", "@type": "@id", "@container": "@list"}}
|
|
],
|
|
"foo": ["http://example.org/foo#bar"]
|
|
}),
|
|
[
|
|
{RDF.bnode("b0"), ~I<http://example.org/foo#bar>, RDF.bnode("b1")},
|
|
{RDF.bnode("b1"), NS.RDF.first, ~I<http://example.org/foo#bar>},
|
|
{RDF.bnode("b1"), NS.RDF.rest, NS.RDF.nil},
|
|
]
|
|
},
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test "term def with @id + @type + @container list: #{title}", %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
describe "blank node predicates" do
|
|
setup do
|
|
{:ok, input: ~s({"@id": "http://example/subj", "_:foo": "bar"})}
|
|
end
|
|
|
|
test "outputs statements with blank node predicates if :produceGeneralizedRdf is true",
|
|
%{input: input} do
|
|
dataset = JSON.LD.Decoder.decode!(input, produce_generalized_rdf: true)
|
|
assert RDF.Dataset.statement_count(dataset) == 1
|
|
end
|
|
|
|
test "rejects statements with blank node predicates if :produceGeneralizedRdf is false",
|
|
%{input: input} do
|
|
dataset = JSON.LD.Decoder.decode!(input, produce_generalized_rdf: false)
|
|
assert RDF.Dataset.statement_count(dataset) == 0
|
|
end
|
|
end
|
|
|
|
describe "advanced features" do
|
|
%{
|
|
"number syntax (decimal)" =>
|
|
{
|
|
~s({"@context": { "measure": "http://example/measure#"}, "measure:cups": 5.3}),
|
|
{RDF.bnode("b0"), ~I<http://example/measure#cups>, RDF.literal("5.3E0", datatype: XSD.double)}
|
|
},
|
|
"number syntax (double)" =>
|
|
{
|
|
~s({"@context": { "measure": "http://example/measure#"}, "measure:cups": 5.3e0}),
|
|
{RDF.bnode("b0"), ~I<http://example/measure#cups>, RDF.literal("5.3E0", datatype: XSD.double)}
|
|
},
|
|
"number syntax (integer)" =>
|
|
{
|
|
~s({"@context": { "chem": "http://example/chem#"}, "chem:protons": 12}),
|
|
{RDF.bnode("b0"), ~I<http://example/chem#protons>, RDF.literal("12", datatype: XSD.integer)}
|
|
},
|
|
"boolan syntax" =>
|
|
{
|
|
~s({"@context": { "sensor": "http://example/sensor#"}, "sensor:active": true}),
|
|
{RDF.bnode("b0"), ~I<http://example/sensor#active>, RDF.literal("true", datatype: XSD.boolean)}
|
|
},
|
|
"Array top element" =>
|
|
{
|
|
~s([
|
|
{"@id": "http://example.com/#me", "@type": "http://xmlns.com/foaf/0.1/Person"},
|
|
{"@id": "http://example.com/#you", "@type": "http://xmlns.com/foaf/0.1/Person"}
|
|
]),
|
|
[
|
|
{~I<http://example.com/#me>, NS.RDF.type, ~I<http://xmlns.com/foaf/0.1/Person>},
|
|
{~I<http://example.com/#you>, NS.RDF.type, ~I<http://xmlns.com/foaf/0.1/Person>}
|
|
]
|
|
},
|
|
"@graph with array of objects value" =>
|
|
{
|
|
~s({
|
|
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
|
"@graph": [
|
|
{"@id": "http://example.com/#me", "@type": "foaf:Person"},
|
|
{"@id": "http://example.com/#you", "@type": "foaf:Person"}
|
|
]
|
|
}),
|
|
[
|
|
{~I<http://example.com/#me>, NS.RDF.type, ~I<http://xmlns.com/foaf/0.1/Person>},
|
|
{~I<http://example.com/#you>, NS.RDF.type, ~I<http://xmlns.com/foaf/0.1/Person>}
|
|
]
|
|
},
|
|
"XMLLiteral" =>
|
|
{
|
|
~s({
|
|
"http://rdfs.org/sioc/ns#content": {
|
|
"@value": "foo",
|
|
"@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"
|
|
}
|
|
}),
|
|
{RDF.bnode("b0"), ~I<http://rdfs.org/sioc/ns#content>, RDF.literal("foo", datatype: "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral")}
|
|
}
|
|
}
|
|
|> Enum.each(fn ({title, data}) ->
|
|
@tag data: data
|
|
test title, %{data: {input, output}} do
|
|
assert JSON.LD.Decoder.decode!(input) == RDF.Dataset.new(output)
|
|
end
|
|
end)
|
|
end
|
|
|
|
end
|