UNPKG

@inrupt/solid-client

Version:

Make your web apps work with Solid Pods.

1,778 lines (1,554 loc) • 99.6 kB
// Copyright Inrupt Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the // Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // import { describe, it, expect } from "@jest/globals"; import type { NamedNode, Literal, BlankNode } from "@rdfjs/types"; import { DataFactory } from "n3"; import type { IriString, Thing, UrlString } from "../interfaces"; import { getUrl, getBoolean, getDatetime, getDate, getTime, getDecimal, getInteger, getStringEnglish, getStringWithLocale, getStringNoLocale, getLiteral, getNamedNode, getUrlAll, getBooleanAll, getDatetimeAll, getDateAll, getTimeAll, getDecimalAll, getIntegerAll, getStringEnglishAll, getStringWithLocaleAll, getStringByLocaleAll, getStringNoLocaleAll, getLiteralAll, getNamedNodeAll, getTerm, getTermAll, getIriAll, getPropertyAll, } from "./get"; import { xmlSchemaTypes } from "../datatypes"; import { createThing, ValidPropertyUrlExpectedError } from "./thing"; import { mockThingFrom } from "./mock"; import { localNodeSkolemPrefix } from "../rdf.internal"; import { addStringNoLocale } from "./add"; import { removeStringNoLocale } from "./remove"; const SUBJECT = "https://arbitrary.vocab/subject"; const PREDICATE = "https://some.vocab/predicate"; function getMockThingWithLiteralFor( predicate: IriString, literalValue: string, literalType: | "string" | "integer" | "decimal" | "boolean" | "dateTime" | "date" | "time", ): Thing { return { type: "Subject", url: "https://arbitrary.vocab/subject", predicates: { [predicate]: { literals: { [`http://www.w3.org/2001/XMLSchema#${literalType}`]: [literalValue], }, }, }, }; } function getMockThingWithLiteralsFor( predicate: IriString, literal1Value: string, literal2Value: string, literalType: | "string" | "integer" | "decimal" | "boolean" | "dateTime" | "date" | "time", ): Thing { return { type: "Subject", url: "https://arbitrary.vocab/subject", predicates: { [predicate]: { literals: { [`http://www.w3.org/2001/XMLSchema#${literalType}`]: [ literal1Value, literal2Value, ], }, }, }, }; } describe("getPropertyAll", () => { it("returns all Properties for which a value is defined", () => { const mockThing = getMockThingWithLiteralsFor( "https://some.vocab/predicate1", "value1", "value2", "string", ); expect(getPropertyAll(mockThing)).toStrictEqual([ "https://some.vocab/predicate1", ]); }); it("returns all Properties for which a value is defined, excluding Properties that no longer have a value", () => { let mockThing = getMockThingWithLiteralsFor( "https://some.vocab/predicate1", "value1", "value2", "string", ); mockThing = addStringNoLocale( mockThing, "https://arbitrary.vocab/predicate2", "value 3", ); mockThing = addStringNoLocale( mockThing, "https://some.vocab/predicate3", "value 4", ); mockThing = removeStringNoLocale( mockThing, "https://arbitrary.vocab/predicate2", "value 3", ); expect(getPropertyAll(mockThing)).toStrictEqual([ "https://some.vocab/predicate1", "https://some.vocab/predicate3", ]); }); it("returns an empty array for an empty Thing", () => { expect(getPropertyAll(createThing())).toStrictEqual([]); }); }); describe("getIri", () => { function getMockThingWithIri( predicate: IriString, iri: IriString = "https://arbitrary.vocab/object", ): Thing { const thing: Thing = { type: "Subject", url: "https://arbitrary.vocab/subject", predicates: { [predicate]: { namedNodes: [iri], }, }, }; return thing; } it("returns the IRI value for the given Property", () => { const thingWithIri = getMockThingWithIri( "https://some.vocab/predicate", "https://some.vocab/object", ); expect(getUrl(thingWithIri, "https://some.vocab/predicate")).toBe( "https://some.vocab/object", ); }); it("accepts Properties as Named Nodes", () => { const thingWithIri = getMockThingWithIri( "https://some.vocab/predicate", "https://some.vocab/object", ); expect( getUrl( thingWithIri, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toBe("https://some.vocab/object"); }); it("returns an LocalNode if that is the first match", () => { const thingWithIriAndLocalNode = getMockThingWithIri( "https://some.vocab/predicate", `${localNodeSkolemPrefix}someLocalNode`, ); ( thingWithIriAndLocalNode.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[] ).push("https://some.vocab/object"); expect( getUrl(thingWithIriAndLocalNode, "https://some.vocab/predicate"), ).toBe("#someLocalNode"); }); it("returns null if no IRI value was found", () => { const thingWithoutIri = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect(getUrl(thingWithoutIri, "https://some.vocab/predicate")).toBeNull(); }); it("returns LocalNodes", () => { const thingWithIri = getMockThingWithIri( "https://some.vocab/predicate", `${localNodeSkolemPrefix}someLocalNode`, ); expect(getUrl(thingWithIri, "https://some.vocab/predicate")).toBe( "#someLocalNode", ); }); it("does not return non-IRI values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = [ "https://some.vocab/object", "https://arbitrary.vocab/object", ]; expect( getUrl(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toBe("https://some.vocab/object"); }); it("returns null if no IRI value was found for the given Predicate", () => { const thingWithIri = getMockThingWithIri("https://some.vocab/predicate"); expect( getUrl(thingWithIri, "https://some-other.vocab/predicate"), ).toBeNull(); }); it("throws an error when passed something other than a Thing", () => { expect(() => getUrl(null as unknown as Thing, "https://arbitrary.vocab/predicate"), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getUrl( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getUrl( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getIriAll", () => { function getMockThingWithIris( predicate: IriString, iri1: IriString = "https://arbitrary.vocab/object1", iri2: IriString = "https://arbitrary.vocab/object2", ): Thing { return { type: "Subject", url: "https://arbitrary.vocab/subject", predicates: { [predicate]: { namedNodes: [iri1, iri2], }, }, }; } it("returns the IRI values for the given Predicate", () => { const thingWithIris = getMockThingWithIris( "https://some.vocab/predicate", "https://some.vocab/object1", "https://some.vocab/object2", ); expect(getUrlAll(thingWithIris, "https://some.vocab/predicate")).toEqual([ "https://some.vocab/object1", "https://some.vocab/object2", ]); }); it("accepts Properties as Named Nodes", () => { const thingWithIris = getMockThingWithIris( "https://some.vocab/predicate", "https://some.vocab/object1", "https://some.vocab/object2", ); expect( getUrlAll( thingWithIris, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toEqual(["https://some.vocab/object1", "https://some.vocab/object2"]); }); it("returns an empty array if no IRI value was found", () => { const thingWithoutIris = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect(getUrlAll(thingWithoutIris, "https://some.vocab/predicate")).toEqual( [], ); }); it("does not return non-IRI values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://some.vocab/object"]; expect( getUrlAll(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toEqual(["https://some.vocab/object"]); }); it("returns an empty array if no IRI value was found for the given Predicate", () => { const thingWithIri = getMockThingWithIris("https://some.vocab/predicate"); expect( getUrlAll(thingWithIri, "https://some-other.vocab/predicate"), ).toEqual([]); }); it("throws an error when passed something other than a Thing", () => { expect(() => getUrlAll(null as unknown as Thing, "https://arbitrary.vocab/predicate"), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getUrlAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getIriAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getBoolean", () => { it("returns the boolean value for the given Predicate", () => { const thingWithBoolean = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1", "boolean", ); expect(getBoolean(thingWithBoolean, "https://some.vocab/predicate")).toBe( true, ); }); it("accepts Properties as Named Nodes", () => { const thingWithBoolean = getMockThingWithLiteralFor( "https://some.vocab/predicate", "0", "boolean", ); expect( getBoolean( thingWithBoolean, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toBe(false); }); it("returns null if no boolean value was found", () => { const thingWithoutBoolean = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getBoolean(thingWithoutBoolean, "https://some.vocab/predicate"), ).toBeNull(); }); it("does not return non-boolean values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#boolean"] as string[]) = [ "1", ]; expect( getBoolean(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toBe(true); }); it("returns null if no boolean value was found for the given Predicate", () => { const thingWithBoolean = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1", "boolean", ); expect( getBoolean(thingWithBoolean, "https://some-other.vocab/predicate"), ).toBeNull(); }); it("returns null if an invalid value, marked as boolean, was found for the given Predicate", () => { const thingWithNonBoolean = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Not a boolean", "boolean", ); expect( getBoolean(thingWithNonBoolean, "https://some.vocab/predicate"), ).toBeNull(); }); it("throws an error when passed something other than a Thing", () => { expect(() => getBoolean(null as unknown as Thing, "https://arbitrary.vocab/predicate"), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getBoolean( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getBoolean( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getBooleanAll", () => { it("returns the boolean values for the given Predicate", () => { const thingWithBooleans = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "1", "0", "boolean", ); expect( getBooleanAll(thingWithBooleans, "https://some.vocab/predicate"), ).toEqual([true, false]); }); it("accepts Properties as Named Nodes", () => { const thingWithBooleans = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "1", "0", "boolean", ); expect( getBooleanAll( thingWithBooleans, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toEqual([true, false]); }); it("returns an empty array if no boolean values were found", () => { const thingWithoutBooleans = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getBooleanAll(thingWithoutBooleans, "https://some.vocab/predicate"), ).toEqual([]); }); it("does not return non-boolean values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#boolean"] as string[]) = [ "1", ]; expect( getBooleanAll( thingWithDifferentDatatypes, "https://some.vocab/predicate", ), ).toEqual([true]); }); it("returns an empty array if no boolean values were found for the given Predicate", () => { const thingWithBoolean = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1", "boolean", ); expect( getBooleanAll(thingWithBoolean, "https://some-other.vocab/predicate"), ).toEqual([]); }); it("does not include invalid values marked as boolean", () => { const thingWithNonBoolean = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "Not a boolean", "0", "boolean", ); expect( getBooleanAll(thingWithNonBoolean, "https://some.vocab/predicate"), ).toEqual([false]); }); it("throws an error when passed something other than a Thing", () => { expect(() => getBooleanAll( null as unknown as Thing, "https://arbitrary.vocab/predicate", ), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getBooleanAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getBooleanAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getDatetime", () => { it("returns the datetime value for the given Predicate", () => { const thingWithDatetime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1990-11-12T13:37:42.000Z", "dateTime", ); const expectedDate = new Date(Date.UTC(1990, 10, 12, 13, 37, 42, 0)); expect( getDatetime(thingWithDatetime, "https://some.vocab/predicate"), ).toEqual(expectedDate); }); it("accepts Properties as Named Nodes", () => { const thingWithDatetime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1990-11-12T13:37:42.000Z", "dateTime", ); const expectedDate = new Date(Date.UTC(1990, 10, 12, 13, 37, 42, 0)); expect( getDatetime( thingWithDatetime, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toEqual(expectedDate); }); it("returns null if no datetime value was found", () => { const thingWithoutDatetime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getDatetime(thingWithoutDatetime, "https://some.vocab/predicate"), ).toBeNull(); }); it("does not return non-datetime values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#dateTime"] as string[]) = [ "1990-11-12T13:37:42.000Z", ]; const expectedDate = new Date(Date.UTC(1990, 10, 12, 13, 37, 42, 0)); expect( getDatetime(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toEqual(expectedDate); }); it("returns null if no datetime value was found for the given Predicate", () => { const thingWithDatetime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1990-11-12T13:37:42.000Z", "dateTime", ); expect( getDatetime(thingWithDatetime, "https://some-other.vocab/predicate"), ).toBeNull(); }); it("returns null if an invalid value, marked as datetime, was found for the given Predicate", () => { const thingWithNonDatetime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Not a datetime", "dateTime", ); expect( getDatetime(thingWithNonDatetime, "https://some.vocab/predicate"), ).toBeNull(); }); it("throws an error when passed something other than a Thing", () => { expect(() => getDatetime( null as unknown as Thing, "https://arbitrary.vocab/predicate", ), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getDatetime( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getDatetime( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getDatetimeAll", () => { it("returns the datetime values for the given Predicate", () => { const thingWithDatetimes = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "1955-06-08T13:37:42.000Z", "1990-11-12T13:37:42.000Z", "dateTime", ); const expectedDate1 = new Date(Date.UTC(1955, 5, 8, 13, 37, 42, 0)); const expectedDate2 = new Date(Date.UTC(1990, 10, 12, 13, 37, 42, 0)); expect( getDatetimeAll(thingWithDatetimes, "https://some.vocab/predicate"), ).toEqual([expectedDate1, expectedDate2]); }); it("accepts Properties as Named Nodes", () => { const thingWithDatetimes = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "1955-06-08T13:37:42.000Z", "1990-11-12T13:37:42.000Z", "dateTime", ); const expectedDate1 = new Date(Date.UTC(1955, 5, 8, 13, 37, 42, 0)); const expectedDate2 = new Date(Date.UTC(1990, 10, 12, 13, 37, 42, 0)); expect( getDatetimeAll( thingWithDatetimes, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toEqual([expectedDate1, expectedDate2]); }); it("returns an empty array if no datetime values were found", () => { const thingWithoutDatetimes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getDatetimeAll(thingWithoutDatetimes, "https://some.vocab/predicate"), ).toEqual([]); }); it("does not return non-datetime values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#dateTime"] as string[]) = [ "1990-11-12T13:37:42.000Z", ]; const expectedDate = new Date(Date.UTC(1990, 10, 12, 13, 37, 42, 0)); expect( getDatetimeAll( thingWithDifferentDatatypes, "https://some.vocab/predicate", ), ).toEqual([expectedDate]); }); it("returns an empty array if no datetime values were found for the given Predicate", () => { const thingWithDatetime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1990-11-12T13:37:42.000Z", "dateTime", ); expect( getDatetimeAll(thingWithDatetime, "https://some-other.vocab/predicate"), ).toEqual([]); }); it("does not return invalid values marked as datetime", () => { const thingWithNonDatetime = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "Not a datetime", "1990-11-12T13:37:42.000Z", "dateTime", ); const expectedDate = new Date(Date.UTC(1990, 10, 12, 13, 37, 42, 0)); expect( getDatetimeAll(thingWithNonDatetime, "https://some.vocab/predicate"), ).toEqual([expectedDate]); }); it("throws an error when passed something other than a Thing", () => { expect(() => getDatetimeAll( null as unknown as Thing, "https://arbitrary.vocab/predicate", ), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getDatetimeAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getDatetimeAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getDate", () => { it("returns the date value for the given Predicate", () => { const thingWithDate = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1990-11-12Z", "date", ); const expectedDate = new Date(Date.UTC(1990, 10, 12, 12)); expect(getDate(thingWithDate, "https://some.vocab/predicate")).toEqual( expectedDate, ); }); it("accepts Properties as Named Nodes", () => { const thingWithDate = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1990-11-12Z", "date", ); const expectedDate = new Date(Date.UTC(1990, 10, 12, 12)); expect( getDate( thingWithDate, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toEqual(expectedDate); }); it("returns null if no date value was found", () => { const thingWithoutDate = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getDate(thingWithoutDate, "https://some.vocab/predicate"), ).toBeNull(); }); it("does not return non-date values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#date"] as string[]) = [ "1990-11-12Z", ]; const expectedDate = new Date(Date.UTC(1990, 10, 12, 12)); expect( getDate(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toEqual(expectedDate); }); it("returns null if no date value was found for the given Predicate", () => { const thingWithDate = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1990-11-12", "date", ); expect( getDate(thingWithDate, "https://some-other.vocab/predicate"), ).toBeNull(); }); it("returns null if an invalid value, marked as date, was found for the given Predicate", () => { const thingWithNonDate = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Not a date", "date", ); expect( getDate(thingWithNonDate, "https://some.vocab/predicate"), ).toBeNull(); }); it("throws an error when passed something other than a Thing", () => { expect(() => getDate(null as unknown as Thing, "https://arbitrary.vocab/predicate"), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getDate( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getDate( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getDateAll", () => { it("returns the date values for the given Predicate", () => { const thingWithDates = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "1955-06-08", "1990-11-12", "date", ); const expectedDate1 = new Date(Date.UTC(1955, 5, 8, 12)); const expectedDate2 = new Date(Date.UTC(1990, 10, 12, 12)); expect(getDateAll(thingWithDates, "https://some.vocab/predicate")).toEqual([ expectedDate1, expectedDate2, ]); }); it("accepts Properties as Named Nodes", () => { const thingWithDates = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "1955-06-08", "1990-11-12", "date", ); const expectedDate1 = new Date(Date.UTC(1955, 5, 8, 12)); const expectedDate2 = new Date(Date.UTC(1990, 10, 12, 12)); expect( getDateAll( thingWithDates, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toEqual([expectedDate1, expectedDate2]); }); it("returns an empty array if no date values were found", () => { const thingWithoutDates = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getDateAll(thingWithoutDates, "https://some.vocab/predicate"), ).toEqual([]); }); it("does not return non-date values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#date"] as string[]) = [ "1990-11-12", ]; const expectedDate = new Date(Date.UTC(1990, 10, 12, 12)); expect( getDateAll(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toEqual([expectedDate]); }); it("returns an empty array if no date values were found for the given Predicate", () => { const thingWithDate = getMockThingWithLiteralFor( "https://some.vocab/predicate", "1990-11-12", "date", ); expect( getDateAll(thingWithDate, "https://some-other.vocab/predicate"), ).toEqual([]); }); it("does not return invalid values marked as date", () => { const thingWithNonDate = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "Not a date", "1990-11-12", "date", ); const expectedDate = new Date(Date.UTC(1990, 10, 12, 12)); expect( getDateAll(thingWithNonDate, "https://some.vocab/predicate"), ).toEqual([expectedDate]); }); it("throws an error when passed something other than a Thing", () => { expect(() => getDateAll(null as unknown as Thing, "https://arbitrary.vocab/predicate"), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getDateAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getDateAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getTime", () => { it("returns the time value for the given Predicate", () => { const thingWithTime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13:37:42", "time", ); const expectedTime = { hour: 13, minute: 37, second: 42, }; expect( getTime(thingWithTime, "https://some.vocab/predicate"), ).toStrictEqual(expectedTime); }); it("accepts Properties as Named Nodes", () => { const thingWithTime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13:37:42", "time", ); const expectedTime = { hour: 13, minute: 37, second: 42, }; expect( getTime( thingWithTime, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toStrictEqual(expectedTime); }); it("returns null if no time value was found", () => { const thingWithoutTime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getTime(thingWithoutTime, "https://some.vocab/predicate"), ).toBeNull(); }); it("does not return non-time values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#time"] as string[]) = [ "13:37:42", ]; const expectedTime = { hour: 13, minute: 37, second: 42, }; expect( getTime(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toStrictEqual(expectedTime); }); it("returns null if no time value was found for the given Predicate", () => { const thingWithTime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13:37:42", "time", ); expect( getTime(thingWithTime, "https://some-other.vocab/predicate"), ).toBeNull(); }); it("returns null if an invalid value, marked as time, was found for the given Predicate", () => { const thingWithNonTime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Not a time", "time", ); expect( getTime(thingWithNonTime, "https://some.vocab/predicate"), ).toBeNull(); }); it("throws an error when passed something other than a Thing", () => { expect(() => getTime(null as unknown as Thing, "https://arbitrary.vocab/predicate"), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getTime( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getTime( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getTimeAll", () => { it("returns the time values for the given Predicate", () => { const thingWithTimes = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "14:37:42", "13:37:42", "time", ); const expectedTime1 = { hour: 14, minute: 37, second: 42, }; const expectedTime2 = { hour: 13, minute: 37, second: 42, }; expect( getTimeAll(thingWithTimes, "https://some.vocab/predicate"), ).toStrictEqual([expectedTime1, expectedTime2]); }); it("accepts Properties as Named Nodes", () => { const thingWithTimes = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "14:37:42", "13:37:42", "time", ); const expectedTime1 = { hour: 14, minute: 37, second: 42, }; const expectedTime2 = { hour: 13, minute: 37, second: 42, }; expect( getTimeAll( thingWithTimes, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toStrictEqual([expectedTime1, expectedTime2]); }); it("returns an empty array if no time values were found", () => { const thingWithoutTimes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getTimeAll(thingWithoutTimes, "https://some.vocab/predicate"), ).toStrictEqual([]); }); it("does not return non-time values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#time"] as string[]) = [ "13:37:42", ]; const expectedTime = { hour: 13, minute: 37, second: 42, }; expect( getTimeAll(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toStrictEqual([expectedTime]); }); it("returns an empty array if no time values were found for the given Predicate", () => { const thingWithTime = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13:37:42", "time", ); expect( getTimeAll(thingWithTime, "https://some-other.vocab/predicate"), ).toStrictEqual([]); }); it("does not return invalid values marked as time", () => { const thingWithNonTime = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "Not a time", "13:37:42", "time", ); const expectedTime = { hour: 13, minute: 37, second: 42, }; expect( getTimeAll(thingWithNonTime, "https://some.vocab/predicate"), ).toStrictEqual([expectedTime]); }); it("throws an error when passed something other than a Thing", () => { expect(() => getTimeAll(null as unknown as Thing, "https://arbitrary.vocab/predicate"), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getTimeAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getTimeAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getDecimal", () => { it("returns the decimal value for the given Predicate", () => { const thingWithDecimal = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13.37", "decimal", ); expect(getDecimal(thingWithDecimal, "https://some.vocab/predicate")).toBe( 13.37, ); }); it("accepts Properties as Named Nodes", () => { const thingWithDecimal = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13.37", "decimal", ); expect( getDecimal( thingWithDecimal, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toBe(13.37); }); it("returns null if no decimal value was found", () => { const thingWithoutDecimal = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getDecimal(thingWithoutDecimal, "https://some.vocab/predicate"), ).toBeNull(); }); it("does not return non-decimal values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#decimal"] as string[]) = [ "13.37", ]; expect( getDecimal(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toBe(13.37); }); it("returns null if no decimal value was found for the given Predicate", () => { const thingWithDecimal = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13.37", "decimal", ); expect( getDecimal(thingWithDecimal, "https://some-other.vocab/predicate"), ).toBeNull(); }); it("throws an error when passed something other than a Thing", () => { expect(() => getDecimal(null as unknown as Thing, "https://arbitrary.vocab/predicate"), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getDecimal( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getDecimal( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getDecimalAll", () => { it("returns the decimal values for the given Predicate", () => { const thingWithDecimals = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "13.37", "7.2", "decimal", ); expect( getDecimalAll(thingWithDecimals, "https://some.vocab/predicate"), ).toEqual([13.37, 7.2]); }); it("accepts Properties as Named Nodes", () => { const thingWithDecimals = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "13.37", "7.2", "decimal", ); expect( getDecimalAll( thingWithDecimals, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toEqual([13.37, 7.2]); }); it("returns an empty array if no decimal values were found", () => { const thingWithoutDecimals = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getDecimalAll(thingWithoutDecimals, "https://some.vocab/predicate"), ).toEqual([]); }); it("does not return non-decimal values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#decimal"] as string[]) = [ "13.37", ]; expect( getDecimalAll( thingWithDifferentDatatypes, "https://some.vocab/predicate", ), ).toEqual([13.37]); }); it("returns an empty array if no decimal values were found for the given Predicate", () => { const thingWithDecimal = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13.37", "decimal", ); expect( getDecimalAll(thingWithDecimal, "https://some-other.vocab/predicate"), ).toEqual([]); }); it("throws an error when passed something other than a Thing", () => { expect(() => getDecimalAll( null as unknown as Thing, "https://arbitrary.vocab/predicate", ), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getDecimalAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getDecimalAll( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getInteger", () => { it("returns the integer value for the given Predicate", () => { const thingWithInteger = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect(getInteger(thingWithInteger, "https://some.vocab/predicate")).toBe( 42, ); }); it("accepts Properties as Named Nodes", () => { const thingWithInteger = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getInteger( thingWithInteger, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toBe(42); }); it("returns null if no integer value was found", () => { const thingWithoutInteger = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13.37", "decimal", ); expect( getInteger(thingWithoutInteger, "https://some.vocab/predicate"), ).toBeNull(); }); it("does not return non-integer values", () => { const thingWithDifferentDatatypes = getMockThingWithLiteralFor( "https://some.vocab/predicate", "Arbitrary value", "string", ); (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .namedNodes as UrlString[]) = ["https://arbitrary.vocab/object"]; (thingWithDifferentDatatypes.predicates["https://some.vocab/predicate"] .literals!["http://www.w3.org/2001/XMLSchema#integer"] as string[]) = [ "42", ]; expect( getInteger(thingWithDifferentDatatypes, "https://some.vocab/predicate"), ).toBe(42); }); it("returns null if no integer value was found for the given Predicate", () => { const thingWithInteger = getMockThingWithLiteralFor( "https://some.vocab/predicate", "42", "integer", ); expect( getInteger(thingWithInteger, "https://some-other.vocab/predicate"), ).toBeNull(); }); it("throws an error when passed something other than a Thing", () => { expect(() => getInteger(null as unknown as Thing, "https://arbitrary.vocab/predicate"), ).toThrow("Expected a Thing, but received: [null]."); }); it("throws an error when passed an invalid property URL", () => { expect(() => getInteger( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ), ).toThrow( "Expected a valid URL to identify a property, but received: [not-a-url].", ); }); it("throws an instance of ValidPropertyUrlExpectedError when passed an invalid property URL", () => { let thrownError; try { getInteger( mockThingFrom("https://arbitrary.pod/resource#thing"), "not-a-url", ); } catch (e) { thrownError = e; } expect(thrownError).toBeInstanceOf(ValidPropertyUrlExpectedError); }); }); describe("getIntegerAll", () => { it("returns the integer values for the given Predicate", () => { const thingWithIntegers = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "42", "1337", "integer", ); expect( getIntegerAll(thingWithIntegers, "https://some.vocab/predicate"), ).toEqual([42, 1337]); }); it("accepts Properties as Named Nodes", () => { const thingWithIntegers = getMockThingWithLiteralsFor( "https://some.vocab/predicate", "42", "1337", "integer", ); expect( getIntegerAll( thingWithIntegers, DataFactory.namedNode("https://some.vocab/predicate"), ), ).toEqual([42, 1337]); }); it("returns an empty array if no integer values were found", () => { const thingWithoutIntegers = getMockThingWithLiteralFor( "https://some.vocab/predicate", "13.37", "decimal", ); expect( getIntegerAll(thingWithoutIntegers, "https://some.vocab/predicate"), ).toEqual([]); }); it("does not return non-integer values", () => { const thingWithDiffere