Added more integration tests

main
jaxoncreed 2 years ago
parent c0d32e983f
commit 43376bced6
  1. 25
      packages/solid/src/SolidLdoDataset.ts
  2. 4
      packages/solid/src/createSolidLdoDataset.ts
  3. 6
      packages/solid/src/methods.ts
  4. 1
      packages/solid/src/requester/requests/uploadResource.ts
  5. 4
      packages/solid/src/requester/results/success/UpdateSuccess.ts
  6. 23
      packages/solid/src/resource/Container.ts
  7. 31
      packages/solid/test/.ldo/post.context.ts
  8. 155
      packages/solid/test/.ldo/post.schema.ts
  9. 19
      packages/solid/test/.ldo/post.shapeTypes.ts
  10. 45
      packages/solid/test/.ldo/post.typings.ts
  11. 372
      packages/solid/test/Integration.test.ts

@ -9,7 +9,10 @@ import type {
import { AggregateError } from "./requester/results/error/ErrorResult";
import { InvalidUriError } from "./requester/results/error/InvalidUriError";
import type { AggregateSuccess } from "./requester/results/success/SuccessResult";
import type { UpdateSuccess } from "./requester/results/success/UpdateSuccess";
import type {
UpdateDefaultGraphSuccess,
UpdateSuccess,
} from "./requester/results/success/UpdateSuccess";
import type { Container } from "./resource/Container";
import type { Leaf } from "./resource/Leaf";
import type { ResourceResult } from "./resource/resourceResult/ResourceResult";
@ -42,14 +45,18 @@ export class SolidLdoDataset extends LdoDataset {
async commitChangesToPod(
changes: DatasetChanges<Quad>,
): Promise<
| AggregateSuccess<ResourceResult<UpdateSuccess, Leaf>>
| AggregateSuccess<
ResourceResult<UpdateSuccess | UpdateDefaultGraphSuccess, Leaf>
>
| AggregateError<UpdateResultError | InvalidUriError>
> {
const changesByGraph = splitChangesByGraph(changes);
// Iterate through all changes by graph in
const results: [
GraphNode,
DatasetChanges<Quad>,
UpdateResult | InvalidUriError | { type: "defaultGraph"; isError: false },
UpdateResult | InvalidUriError | UpdateDefaultGraphSuccess,
][] = await Promise.all(
Array.from(changesByGraph.entries()).map(
async ([graph, datasetChanges]) => {
@ -59,7 +66,10 @@ export class SolidLdoDataset extends LdoDataset {
return [
graph,
datasetChanges,
{ type: "defaultGraph", isError: false },
{
type: "updateDefaultGraphSuccess",
isError: false,
} as UpdateDefaultGraphSuccess,
];
}
if (isContainerUri(graph.value)) {
@ -94,7 +104,8 @@ export class SolidLdoDataset extends LdoDataset {
.map((result) => result[2])
.filter(
(result): result is ResourceResult<UpdateSuccess, Leaf> =>
result.type === "updateSuccess",
result.type === "updateSuccess" ||
result.type === "updateDefaultGraphSuccess",
),
};
}
@ -111,8 +122,10 @@ export class SolidLdoDataset extends LdoDataset {
createData<Type extends LdoBase>(
shapeType: ShapeType<Type>,
subject: string | SubjectNode,
...resources: Resource[]
resource: Resource,
...additionalResources: Resource[]
): Type {
const resources = [resource, ...additionalResources];
const linkedDataObject = this.usingType(shapeType)
.write(...resources.map((r) => r.uri))
.fromSubject(subject);

@ -2,9 +2,9 @@ import type { Dataset, DatasetFactory } from "@rdfjs/types";
import { SolidLdoDataset } from "./SolidLdoDataset";
import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext";
import crossFetch from "cross-fetch";
import { createDataset, createDatasetFactory } from "@ldo/dataset";
import { ResourceStore } from "./ResourceStore";
import { guaranteeFetch } from "./util/guaranteeFetch";
export interface CreateSolidLdoDatasetOptions {
fetch?: typeof fetch;
@ -15,7 +15,7 @@ export interface CreateSolidLdoDatasetOptions {
export function createSolidLdoDataset(
options?: CreateSolidLdoDatasetOptions,
): SolidLdoDataset {
const finalFetch = options?.fetch || crossFetch;
const finalFetch = guaranteeFetch(options?.fetch);
const finalDatasetFactory = options?.datasetFactory || createDatasetFactory();
const finalDataset = options?.dataset || createDataset();

@ -4,6 +4,7 @@ import {
write,
transactionChanges,
getDataset,
commitTransaction,
} from "@ldo/ldo";
import type { DatasetChanges } from "@ldo/rdf-utils";
import type { Resource } from "./resource/Resource";
@ -17,8 +18,10 @@ import type { Quad } from "@rdfjs/types";
*/
export function changeData<Type extends LdoBase>(
input: Type,
...resources: Resource[]
resource: Resource,
...additionalResources: Resource[]
): Type {
const resources = [resource, ...additionalResources];
// Clone the input and set a graph
const [transactionLdo] = write(...resources.map((r) => r.uri)).usingCopy(
input,
@ -37,6 +40,7 @@ export function commitData(
input: LdoBase,
): ReturnType<SolidLdoDataset["commitChangesToPod"]> {
const changes = transactionChanges(input);
commitTransaction(input);
const dataset = getDataset(input) as SolidLdoDataset;
return dataset.commitChangesToPod(changes as DatasetChanges<Quad>);
}

@ -84,7 +84,6 @@ export async function uploadResource(
};
} catch (err) {
const thing = UnexpectedResourceError.fromThrown(uri, err);
console.log(thing.message);
return thing;
}
}

@ -3,3 +3,7 @@ import type { ResourceSuccess } from "./SuccessResult";
export interface UpdateSuccess extends ResourceSuccess {
type: "updateSuccess";
}
export interface UpdateDefaultGraphSuccess extends ResourceSuccess {
type: "updateDefaultGraphSuccess";
}

@ -114,28 +114,21 @@ export class Container extends Resource {
}
async getRootContainer(): Promise<Container | CheckRootResultError> {
if (this.rootContainer === undefined) {
const checkResult = await this.checkIfIsRootContainer();
if (checkResult.isError) return checkResult;
}
if (this.rootContainer === true) {
const parentContainerResult = await this.getParentContainer();
if (parentContainerResult?.isError) return parentContainerResult;
if (!parentContainerResult) {
return this;
}
const parentUri = getParentUri(this.uri);
if (!parentUri) {
return new NoncompliantPodError(
this.uri,
"Resource does not have a root container",
);
}
return this.context.resourceStore.get(parentUri).getRootContainer();
return parentContainerResult.getRootContainer();
}
async getParentContainer(): Promise<
Container | CheckRootResultError | undefined
> {
const checkResult = await this.checkIfIsRootContainer();
if (checkResult.isError) return checkResult;
if (this.rootContainer === undefined) {
const checkResult = await this.checkIfIsRootContainer();
if (checkResult.isError) return checkResult;
}
if (this.rootContainer) return undefined;
const parentUri = getParentUri(this.uri);
if (!parentUri) {

@ -0,0 +1,31 @@
import { ContextDefinition } from "jsonld";
/**
* =============================================================================
* postContext: JSONLD Context for post
* =============================================================================
*/
export const postContext: ContextDefinition = {
type: {
"@id": "@type",
},
SocialMediaPosting: "http://schema.org/SocialMediaPosting",
CreativeWork: "http://schema.org/CreativeWork",
Thing: "http://schema.org/Thing",
articleBody: {
"@id": "http://schema.org/articleBody",
"@type": "http://www.w3.org/2001/XMLSchema#string",
},
uploadDate: {
"@id": "http://schema.org/uploadDate",
"@type": "http://www.w3.org/2001/XMLSchema#date",
},
image: {
"@id": "http://schema.org/image",
"@type": "@id",
},
publisher: {
"@id": "http://schema.org/publisher",
"@type": "@id",
},
};

@ -0,0 +1,155 @@
import { Schema } from "shexj";
/**
* =============================================================================
* postSchema: ShexJ Schema for post
* =============================================================================
*/
export const postSchema: Schema = {
type: "Schema",
shapes: [
{
id: "https://example.com/PostSh",
type: "ShapeDecl",
shapeExpr: {
type: "Shape",
expression: {
type: "EachOf",
expressions: [
{
type: "TripleConstraint",
predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
valueExpr: {
type: "NodeConstraint",
values: [
"http://schema.org/SocialMediaPosting",
"http://schema.org/CreativeWork",
"http://schema.org/Thing",
],
},
},
{
type: "TripleConstraint",
predicate: "http://schema.org/articleBody",
valueExpr: {
type: "NodeConstraint",
datatype: "http://www.w3.org/2001/XMLSchema#string",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#label",
object: {
value: "articleBody",
},
},
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "The actual body of the article. ",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://schema.org/uploadDate",
valueExpr: {
type: "NodeConstraint",
datatype: "http://www.w3.org/2001/XMLSchema#date",
},
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#label",
object: {
value: "uploadDate",
},
},
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value:
"Date when this media object was uploaded to this site.",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://schema.org/image",
valueExpr: {
type: "NodeConstraint",
nodeKind: "iri",
},
min: 0,
max: 1,
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#label",
object: {
value: "image",
},
},
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value:
"A media object that encodes this CreativeWork. This property is a synonym for encoding.",
},
},
],
},
{
type: "TripleConstraint",
predicate: "http://schema.org/publisher",
valueExpr: {
type: "NodeConstraint",
nodeKind: "iri",
},
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#label",
object: {
value: "publisher",
},
},
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value: "The publisher of the creative work.",
},
},
],
},
],
},
annotations: [
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#label",
object: {
value: "SocialMediaPost",
},
},
{
type: "Annotation",
predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
object: {
value:
"A post to a social media platform, including blog posts, tweets, Facebook posts, etc.",
},
},
],
},
},
],
};

@ -0,0 +1,19 @@
import { ShapeType } from "@ldo/ldo";
import { postSchema } from "./post.schema";
import { postContext } from "./post.context";
import { PostSh } from "./post.typings";
/**
* =============================================================================
* LDO ShapeTypes post
* =============================================================================
*/
/**
* PostSh ShapeType
*/
export const PostShShapeType: ShapeType<PostSh> = {
schema: postSchema,
shape: "https://example.com/PostSh",
context: postContext,
};

@ -0,0 +1,45 @@
import { ContextDefinition } from "jsonld";
/**
* =============================================================================
* Typescript Typings for post
* =============================================================================
*/
/**
* PostSh Type
*/
export interface PostSh {
"@id"?: string;
"@context"?: ContextDefinition;
type:
| {
"@id": "SocialMediaPosting";
}
| {
"@id": "CreativeWork";
}
| {
"@id": "Thing";
};
/**
* The actual body of the article.
*/
articleBody?: string;
/**
* Date when this media object was uploaded to this site.
*/
uploadDate: string;
/**
* A media object that encodes this CreativeWork. This property is a synonym for encoding.
*/
image?: {
"@id": string;
};
/**
* The publisher of the creative work.
*/
publisher: {
"@id": string;
};
}

@ -7,23 +7,41 @@ import type {
SolidLdoDataset,
UpdateResultError,
} from "../src";
import { createSolidLdoDataset } from "../src";
import { changeData, commitData, createSolidLdoDataset } from "../src";
import {
ROOT_CONTAINER,
createApp,
getAuthenticatedFetch,
} from "./solidServer.helper";
import { namedNode, quad as createQuad, literal } from "@rdfjs/data-model";
import {
namedNode,
quad as createQuad,
literal,
defaultGraph,
} from "@rdfjs/data-model";
import type { CreateSuccess } from "../src/requester/results/success/CreateSuccess";
import type { DatasetChanges } from "@ldo/rdf-utils";
import { createDataset } from "@ldo/dataset";
import type { Quad } from "@rdfjs/types";
import type { AggregateSuccess } from "../src/requester/results/success/SuccessResult";
import type { UpdateSuccess } from "../src/requester/results/success/UpdateSuccess";
import type {
UpdateDefaultGraphSuccess,
UpdateSuccess,
} from "../src/requester/results/success/UpdateSuccess";
import type { ResourceSuccess } from "../src/resource/resourceResult/ResourceResult";
import type { AggregateError } from "../src/requester/results/error/ErrorResult";
import type {
AggregateError,
UnexpectedResourceError,
} from "../src/requester/results/error/ErrorResult";
import type { InvalidUriError } from "../src/requester/results/error/InvalidUriError";
import { Buffer } from "buffer";
import { PostShShapeType } from "./.ldo/post.shapeTypes";
import type {
ServerHttpError,
UnauthenticatedHttpError,
UnexpectedHttpError,
} from "../src/requester/results/error/HttpErrorResult";
import type { NoncompliantPodError } from "../src/requester/results/error/NoncompliantPodError";
const TEST_CONTAINER_SLUG = "test_ldo/";
const TEST_CONTAINER_URI =
@ -190,6 +208,28 @@ describe("SolidLdoDataset", () => {
).toBe(1);
});
it("Auto reads a resource", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI, {
autoLoad: true,
});
// Wait until the resource is auto-loaded
await new Promise<void>((resolve) => {
const interval = setInterval(() => {
if (!resource.isReading()) {
clearInterval(interval);
resolve();
}
}, 250);
});
expect(
solidLdoDataset.match(
namedNode("http://example.org/#spiderman"),
namedNode("http://www.perceive.net/schemas/relationship/enemyOf"),
namedNode("http://example.org/#green-goblin"),
).size,
).toBe(1);
});
it("Reads a container", async () => {
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
const result = await testRequestLoads(() => resource.read(), resource, {
@ -326,6 +366,88 @@ describe("SolidLdoDataset", () => {
});
});
/**
* readIfUnfetched
*/
describe("readIfUnfetched", () => {
it("reads an unfetched container", async () => {
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
const result = await testRequestLoads(
() => resource.readIfUnfetched(),
resource,
{
isLoading: true,
isReading: true,
},
);
expect(result.type).toBe("containerReadSuccess");
expect(resource.children().length).toBe(2);
});
it("reads an unfetched leaf", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
const result = await testRequestLoads(
() => resource.readIfUnfetched(),
resource,
{
isLoading: true,
isReading: true,
},
);
expect(result.type).toBe("dataReadSuccess");
expect(
solidLdoDataset.match(
namedNode("http://example.org/#spiderman"),
namedNode("http://www.perceive.net/schemas/relationship/enemyOf"),
namedNode("http://example.org/#green-goblin"),
).size,
).toBe(1);
});
it("returns a cached existing container", async () => {
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
await resource.read();
fetchMock.mockClear();
const result = await resource.readIfUnfetched();
expect(fetchMock).not.toHaveBeenCalled();
expect(result.type).toBe("containerReadSuccess");
expect(resource.children().length).toBe(2);
});
it("returns a cached existing leaf", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
await resource.read();
fetchMock.mockClear();
const result = await resource.readIfUnfetched();
expect(result.type).toBe("dataReadSuccess");
expect(
solidLdoDataset.match(
namedNode("http://example.org/#spiderman"),
namedNode("http://www.perceive.net/schemas/relationship/enemyOf"),
namedNode("http://example.org/#green-goblin"),
).size,
).toBe(1);
});
it("returns a cached absent container", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_CONTAINER_URI);
await resource.read();
fetchMock.mockClear();
const result = await resource.readIfUnfetched();
expect(fetchMock).not.toHaveBeenCalled();
expect(result.type).toBe("absentReadSuccess");
});
it("returns a cached absent leaf", async () => {
const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
await resource.read();
fetchMock.mockClear();
const result = await resource.readIfUnfetched();
expect(fetchMock).not.toHaveBeenCalled();
expect(result.type).toBe("absentReadSuccess");
});
});
/**
* Get Root Container
*/
@ -336,6 +458,7 @@ describe("SolidLdoDataset", () => {
expect(result.type).toBe("container");
if (result.type !== "container") return;
expect(result.uri).toBe(ROOT_CONTAINER);
expect(result.isRootContainer()).toBe(true);
});
it("Returns an error if there is no link header for a container request", async () => {
@ -376,6 +499,22 @@ describe("SolidLdoDataset", () => {
expect(result.type).toBe("unexpectedResourceError");
expect(result.message).toBe("Something happened.");
});
it("returns a NonCompliantPodError when there is no root", async () => {
fetchMock.mockResolvedValueOnce(
new Response(TEST_CONTAINER_TTL, {
status: 200,
headers: new Headers({
"content-type": "text/turtle",
link: '<http://www.w3.org/ns/ldp#Resource>; rel="type"',
}),
}),
);
const resource = solidLdoDataset.getResource(ROOT_CONTAINER);
const result = await resource.getRootContainer();
expect(result.isError).toBe(true);
expect(result.type).toBe("noncompliantPodError");
});
});
/**
@ -520,7 +659,7 @@ describe("SolidLdoDataset", () => {
const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
const result = await testRequestLoads(
() => resource.createAndOverwrite(),
() => resource.createIfAbsent(),
resource,
{
isLoading: true,
@ -573,6 +712,38 @@ describe("SolidLdoDataset", () => {
container.children().some((child) => child.uri === SAMPLE_DATA_URI),
).toBe(true);
});
it("creates a container that doesn't exist", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_CONTAINER_URI);
const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
const result = await testRequestLoads(
() => resource.createIfAbsent(),
resource,
{
isLoading: true,
isCreating: true,
},
);
expect(result.type).toBe("createSuccess");
const createSuccess = result as CreateSuccess;
expect(createSuccess.didOverwrite).toBe(false);
expect(
solidLdoDataset.has(
createQuad(
namedNode(TEST_CONTAINER_URI),
namedNode("http://www.w3.org/ns/ldp#contains"),
namedNode(SAMPLE2_DATA_URI),
namedNode(TEST_CONTAINER_URI),
),
),
).toBe(true);
expect(
container
.children()
.some((child) => child.uri === SAMPLE_CONTAINER_URI),
).toBe(true);
});
});
/**
@ -600,6 +771,76 @@ describe("SolidLdoDataset", () => {
expect(result.isError).toBe(true);
expect(result.type).toBe("unexpectedResourceError");
});
it("deletes a container", async () => {
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
const result = await resource.delete();
expect(result.type === "deleteSuccess");
});
it("returns an error on container read when deleting a container", async () => {
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
fetchMock.mockResolvedValueOnce(
new Response(SAMPLE_DATA_URI, {
status: 500,
}),
);
const result = await resource.delete();
expect(result.isError).toBe(true);
expect(result.type).toBe("aggregateError");
const aggregateError = result as AggregateError<
| ServerHttpError
| UnexpectedHttpError
| UnauthenticatedHttpError
| UnexpectedResourceError
| NoncompliantPodError
>;
expect(aggregateError.errors[0].type).toBe("serverError");
});
it("returns an error on child delete read when deleting a container", async () => {
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
fetchMock.mockImplementationOnce(authFetch);
fetchMock.mockResolvedValueOnce(
new Response(SAMPLE_DATA_URI, {
status: 500,
}),
);
const result = await resource.delete();
expect(result.isError).toBe(true);
expect(result.type).toBe("aggregateError");
const aggregateError = result as AggregateError<
| ServerHttpError
| UnexpectedHttpError
| UnauthenticatedHttpError
| UnexpectedResourceError
| NoncompliantPodError
>;
expect(aggregateError.errors[0].type).toBe("serverError");
});
it("returns an error on container delete read when deleting a container", async () => {
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
fetchMock.mockImplementationOnce(authFetch);
fetchMock.mockImplementationOnce(authFetch);
fetchMock.mockImplementationOnce(authFetch);
fetchMock.mockResolvedValueOnce(
new Response(SAMPLE_DATA_URI, {
status: 500,
}),
);
const result = await resource.delete();
expect(result.isError).toBe(true);
expect(result.type).toBe("aggregateError");
const aggregateError = result as AggregateError<
| ServerHttpError
| UnexpectedHttpError
| UnauthenticatedHttpError
| UnexpectedResourceError
| NoncompliantPodError
>;
expect(aggregateError.errors[0].type).toBe("serverError");
});
});
/**
@ -670,6 +911,59 @@ describe("SolidLdoDataset", () => {
expect(aggregateError.errors.length).toBe(1);
expect(aggregateError.errors[0].type).toBe("unexpectedResourceError");
});
it("errors when trying to update a container", async () => {
const changes: DatasetChanges<Quad> = {
added: createDataset([
createQuad(
namedNode("http://example.org/#green-goblin"),
namedNode("http://xmlns.com/foaf/0.1/name"),
literal("Norman Osborn"),
namedNode(SAMPLE_CONTAINER_URI),
),
]),
};
const result = await solidLdoDataset.commitChangesToPod(changes);
expect(result.isError).toBe(true);
expect(result.type).toBe("aggregateError");
const aggregateError = result as AggregateError<
UpdateResultError | InvalidUriError
>;
expect(aggregateError.errors.length).toBe(1);
expect(aggregateError.errors[0].type === "invalidUriError").toBe(true);
});
it("writes to the default graph without fetching", async () => {
const changes: DatasetChanges<Quad> = {
added: createDataset([
createQuad(
namedNode("http://example.org/#green-goblin"),
namedNode("http://xmlns.com/foaf/0.1/name"),
literal("Norman Osborn"),
defaultGraph(),
),
]),
};
const result = await solidLdoDataset.commitChangesToPod(changes);
expect(result.type).toBe("aggregateSuccess");
const aggregateSuccess = result as AggregateSuccess<
ResourceSuccess<UpdateSuccess | UpdateDefaultGraphSuccess, Leaf>
>;
expect(aggregateSuccess.results.length).toBe(1);
expect(aggregateSuccess.results[0].type).toBe(
"updateDefaultGraphSuccess",
);
expect(
solidLdoDataset.has(
createQuad(
namedNode("http://example.org/#green-goblin"),
namedNode("http://xmlns.com/foaf/0.1/name"),
literal("Norman Osborn"),
defaultGraph(),
),
),
);
});
});
/**
@ -862,4 +1156,72 @@ describe("SolidLdoDataset", () => {
).toBe(true);
});
});
/**
* ===========================================================================
* Methods
* ===========================================================================
*/
describe("methods", () => {
it("creates a data object for a specific subject", () => {
const resource = solidLdoDataset.getResource(
"https://example.com/resource.ttl",
);
const post = solidLdoDataset.createData(
PostShShapeType,
"https://example.com/subject",
resource,
);
post.type = { "@id": "CreativeWork" };
expect(post.type["@id"]).toBe("CreativeWork");
commitData(post);
expect(
solidLdoDataset.has(
createQuad(
namedNode("https://example.com/subject"),
namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
namedNode("http://schema.org/CreativeWork"),
namedNode("https://example.com/resource.ttl"),
),
),
).toBe(true);
});
it("uses changeData to start a transaction", () => {
const resource = solidLdoDataset.getResource(
"https://example.com/resource.ttl",
);
solidLdoDataset.add(
createQuad(
namedNode("https://example.com/subject"),
namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
namedNode("http://schema.org/CreativeWork"),
namedNode("https://example.com/resource.ttl"),
),
);
const post = solidLdoDataset
.usingType(PostShShapeType)
.fromSubject("https://example.com/subject");
const cPost = changeData(post, resource);
cPost.type = { "@id": "SocialMediaPosting" };
expect(cPost.type["@id"]).toBe("SocialMediaPosting");
commitData(cPost);
expect(
solidLdoDataset.has(
createQuad(
namedNode("https://example.com/subject"),
namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
namedNode("http://schema.org/SocialMediaPosting"),
namedNode("https://example.com/resource.ttl"),
),
),
).toBe(true);
});
});
/**
* ===========================================================================
* Container-Specific Methods
* ===========================================================================
*/
});
Loading…
Cancel
Save