UNPKG

@inrupt/solid-client

Version:

Make your web apps work with Solid Pods.

287 lines (251 loc) • 9.28 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 { buildThing } from "./build"; import * as adders from "./add"; import * as setters from "./set"; import * as removers from "./remove"; import { asIri, createThing, isThing } from "./thing"; import type { ThingLocal } from "../interfaces"; import { getInteger, getStringWithLocale } from "./get"; describe("Thing Builder API", () => { it("adds the same properties as non-fluent functions", () => { const startingThing = createThing(); const builtThing = buildThing(startingThing) .addInteger("https://some.vocab/predicate", 42) .addStringEnglish("https://some.vocab/predicate", "Some English string") .addStringWithLocale( "https://some.vocab/predicate", "Some string", "nl-nl", ) .build(); let nonBuilderThing = adders.addInteger( startingThing, "https://some.vocab/predicate", 42, ); nonBuilderThing = adders.addStringEnglish( nonBuilderThing, "https://some.vocab/predicate", "Some English string", ); nonBuilderThing = adders.addStringWithLocale( nonBuilderThing, "https://some.vocab/predicate", "Some string", "nl-nl", ); expect(builtThing).toStrictEqual(nonBuilderThing); }); it("replaces the same properties as the non-fluent functions", () => { let startingThing = adders.addDecimal( createThing(), "https://some.vocab/predicate", 4.2, ); startingThing = adders.addStringWithLocale( startingThing, "https://some-other.vocab/predicate", "Some string", "nl-nl", ); const builtThing = buildThing(startingThing) .setDecimal("https://some.vocab/predicate", 13.37) .setStringEnglish( "https://some-other.vocab/predicate", "Some English string", ) .setStringWithLocale( "https://some-other.vocab/predicate", "Some other string", "nl-nl", ) .build(); let nonBuilderThing = setters.setDecimal( startingThing, "https://some.vocab/predicate", 13.37, ); nonBuilderThing = setters.setStringEnglish( nonBuilderThing, "https://some-other.vocab/predicate", "Some English string", ); nonBuilderThing = setters.setStringWithLocale( nonBuilderThing, "https://some-other.vocab/predicate", "Some other string", "nl-nl", ); expect(builtThing).toStrictEqual(nonBuilderThing); }); it("removes the same properties as the non-fluent functions", () => { let startingThing = adders.addDecimal( createThing(), "https://some.vocab/predicate", 4.2, ); startingThing = adders.addStringEnglish( startingThing, "https://some.vocab/predicate-english", "Some English string", ); startingThing = adders.addStringWithLocale( startingThing, "https://some.vocab/predicate", "Some string", "en-gb", ); startingThing = adders.addBoolean( startingThing, "https://some-other.vocab/predicate", true, ); startingThing = adders.addStringNoLocale( startingThing, "https://yet-another.vocab/predicate", "Some unlocalised string", ); const builtThing = buildThing(startingThing) .removeStringEnglish( "https://some.vocab/predicate-english", "Some English string", ) .removeStringWithLocale( "https://some.vocab/predicate", "Some string", "en-gb", ) .removeBoolean("https://some-other.vocab/predicate", true) .removeAll("https://yet-another.vocab/predicate") .build(); let nonBuilderThing = removers.removeStringEnglish( startingThing, "https://some.vocab/predicate-english", "Some English string", ); nonBuilderThing = removers.removeStringWithLocale( nonBuilderThing, "https://some.vocab/predicate", "Some string", "en-gb", ); nonBuilderThing = removers.removeBoolean( nonBuilderThing, "https://some-other.vocab/predicate", true, ); nonBuilderThing = removers.removeAll( nonBuilderThing, "https://yet-another.vocab/predicate", ); expect(builtThing).toStrictEqual(nonBuilderThing); }); it("initialises a new Thing if not passed one", () => { const thing = buildThing().build(); expect(isThing(thing)).toBe(true); }); it("can take options for the Thing initialisation", () => { const thing = buildThing({ url: "https://some.pod/resource#thing", }).build(); expect(asIri(thing)).toBe("https://some.pod/resource#thing"); }); it("preserves the type (ThingLocal or ThingPersisted) of Things passed to it", () => { // We're only going to check for expected TypeScript errors: expect.assertions(0); /* eslint-disable @typescript-eslint/no-unused-vars */ // @ts-expect-error Since we're passing the `url` option, `buildThing` // should return a ThingPersisted, which should cause an error when // assigning to a ThingLocal variable: const _thingPersistedDirect: ThingLocal = buildThing({ url: "https://some.pod/resource#thing", }).build(); // @ts-expect-error Since we're passing a ThingPersisted as the starting // Thing, `buildThing` should also return a ThingPersisted, which should // cause an error when assigning to a ThingLocal variable: const _thingPersisted: ThingLocal = buildThing( createThing({ url: "https://some.pod/resource#thing" }), ).build(); // Since we're passing the `name` option, `buildThing` should return a ThingLocal, // which should not cause an error when assigning to a ThingLocal variable: const _thingLocalDirect: ThingLocal = buildThing({ name: "thing" }).build(); // Since we're passing a ThingLocal as the starting Thing, // `buildThing` should also return a ThingLocal, // which should not cause an error when assigning to a ThingLocal variable: const _thingLocal: ThingLocal = buildThing( createThing({ name: "thing" }), ).build(); /* eslint-enable @typescript-eslint/no-unused-vars */ }); it("has equivalents for every adder", () => { const adderNames = Object.keys(adders).filter( (adderName) => adderName.substring(0, 3) === "add", ); expect.assertions(adderNames.length * 2); const builder = buildThing(); adderNames.forEach((adderName) => { expect((builder as Record<string, unknown>)[adderName]).toBeDefined(); expect(typeof (builder as Record<string, unknown>)[adderName]).toBe( "function", ); }); }); it("has equivalents for every setter", () => { const setterNames = Object.keys(setters).filter( (setterName) => setterName.substring(0, 3) === "set", ); expect.assertions(setterNames.length * 2); const builder = buildThing(); setterNames.forEach((setterName) => { expect((builder as Record<string, unknown>)[setterName]).toBeDefined(); expect(typeof (builder as Record<string, unknown>)[setterName]).toBe( "function", ); }); }); it("has equivalents for every remover", () => { const removerNames = Object.keys(removers).filter( (removerName) => removerName.substring(0, 6) === "remove", ); expect.assertions(removerNames.length * 2); const builder = buildThing(); removerNames.forEach((removerName) => { expect((builder as Record<string, unknown>)[removerName]).toBeDefined(); expect(typeof (builder as Record<string, unknown>)[removerName]).toBe( "function", ); }); }); it("has methods that need not be chained", () => { const builder = buildThing().addInteger("https://some.vocab/predicate", 42); builder.addStringWithLocale( "https://some.vocab/predicate", "Some string", "nl-nl", ); const thing = builder.build(); expect(getInteger(thing, "https://some.vocab/predicate")).toBe(42); expect( getStringWithLocale(thing, "https://some.vocab/predicate", "nl-nl"), ).toBe("Some string"); }); });