Skip to content

Commit

Permalink
refactor: do not return a function from validate
Browse files Browse the repository at this point in the history
  • Loading branch information
jenspots committed Apr 9, 2024
1 parent b3cc1bf commit acfc3b8
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 73 deletions.
62 changes: 30 additions & 32 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type ValidateArguments = {
validationIsFatal?: boolean;
};

export async function validate(args: ValidateArguments): Promise<() => void> {
export async function validate(args: ValidateArguments): Promise<void> {
const { shaclPath, incoming, outgoing, report } = args;

// Default arguments.
Expand Down Expand Up @@ -50,38 +50,36 @@ export async function validate(args: ValidateArguments): Promise<() => void> {
// @ts-expect-error Factory is valid.
const validator = new Validator(shapes, { factory: rdf });

return () => {
// Anything that passes through this processor and identifies with a
// specific shape should match the SHACL definition.
incoming.on("data", async (data) => {
// Parse data into a dataset.
const rawStream = Readable.from(data);
const quadStream = parser.import(rawStream);
const dataset = await rdf
.dataset()
.import(quadStream)
.catch(() => {
throw ShaclError.invalidRdfFormat();
});
// Anything that passes through this processor and identifies with a
// specific shape should match the SHACL definition.
incoming.on("data", async (data) => {
// Parse data into a dataset.
const rawStream = Readable.from(data);
const quadStream = parser.import(rawStream);
const dataset = await rdf
.dataset()
.import(quadStream)
.catch(() => {
throw ShaclError.invalidRdfFormat();
});

// Run through validator.
const result = await validator.validate({ dataset });
// Run through validator.
const result = await validator.validate({ dataset });

// Pass through data if valid.
if (result.conforms) {
await outgoing.push(data);
} else if (validationIsFatal) {
throw ShaclError.validationFailed();
} else if (report) {
const resultRaw = serializer.transform(result.dataset);
await report.push(resultRaw);
}
});
// Pass through data if valid.
if (result.conforms) {
await outgoing.push(data);
} else if (validationIsFatal) {
throw ShaclError.validationFailed();
} else if (report) {
const resultRaw = serializer.transform(result.dataset);
await report.push(resultRaw);
}
});

// If the input stream closes itself, so should the output streams.
incoming.on("end", () => {
outgoing.end();
report?.end();
});
};
// If the input stream closes itself, so should the output streams.
incoming.on("end", () => {
outgoing.end();
report?.end();
});
}
57 changes: 22 additions & 35 deletions tests/error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,36 @@ import { SimpleStream } from "@ajuvercr/js-runner";
import { ShaclError } from "../src/error";
import fs from "fs";

// Parse input files beforehand and share among tests.
const shaclPath = "./tests/shacl/point.ttl";

const validJsonLd = fs.readFileSync("./tests/data/valid.jsonld").toString();
const invalidRdfData = fs.readFileSync("./tests/data/invalid.ttl").toString();

// These streams can be used as a fallback, and shouldn't contain any tested
// data.
const incoming = new SimpleStream<string>();
const outgoing = new SimpleStream<string>();

describe("errors", () => {
test("invalid shacl file path", async () => {
expect.assertions(1);

const func = () =>
validate({
shaclPath: "/tmp/shacl-doesnt-exist.ttl",
incoming: new SimpleStream<string>(),
outgoing: new SimpleStream<string>(),
});
const func = validate({
shaclPath: "/tmp/shacl-doesnt-exist.ttl",
incoming,
outgoing,
});

expect(func()).rejects.toThrow(ShaclError.fileSystemError());
expect(func).rejects.toThrow(ShaclError.fileSystemError());
});

test("invalid data rdf format", async () => {
expect.assertions(1);

const func = validate({
shaclPath,
incoming: new SimpleStream<string>(),
outgoing: new SimpleStream<string>(),
incoming,
outgoing,
mime: "text/invalid",
});

Expand All @@ -40,8 +45,8 @@ describe("errors", () => {

const func = validate({
shaclPath: "./tests/shacl/invalid.ttl",
incoming: new SimpleStream<string>(),
outgoing: new SimpleStream<string>(),
incoming,
outgoing,
});

expect(func).rejects.toThrowError(ShaclError.invalidRdfFormat());
Expand All @@ -50,59 +55,41 @@ describe("errors", () => {
test("invalid input data", async () => {
expect.assertions(1);

const incoming = new SimpleStream<string>();
const outgoing = new SimpleStream<string>();

const func = await validate({
await validate({
shaclPath,
incoming,
outgoing,
});
func();

expect(
incoming.push("This is not a valid Turtle file!"),
).rejects.toThrow(ShaclError.invalidRdfFormat());

await incoming.end();
await outgoing.end();
});

test("invalid and fatal", async () => {
expect.assertions(1);

const incoming = new SimpleStream<string>();

const func = await validate({
await validate({
shaclPath,
incoming,
outgoing: new SimpleStream<string>(),
outgoing,
validationIsFatal: true,
});
func();

expect(incoming.push(invalidRdfData)).rejects.toThrow(
ShaclError.validationFailed(),
);

await incoming.end();
});

test("incorrect mime", async () => {
expect.assertions(1);

const validJsonLd = fs
.readFileSync("./tests/data/valid.jsonld")
.toString();
const incoming = new SimpleStream<string>();

const func = await validate({
await validate({
shaclPath,
incoming,
outgoing: new SimpleStream<string>(),
outgoing,
mime: "text/turtle",
});
func();

expect(async () => {
await incoming.push(validJsonLd);
Expand Down
10 changes: 4 additions & 6 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { validate } from "../src";
import { SimpleStream } from "@ajuvercr/js-runner";
import { describe, test, expect, beforeEach } from "vitest";
import * as fs from "fs";
import { ShaclError } from "../src/error";

// Channel which streams incoming RDF.
let incoming: SimpleStream<string>;
Expand Down Expand Up @@ -59,14 +58,13 @@ beforeEach(async () => {

describe("shacl", () => {
beforeEach(async () => {
// Restart the processor, which is the same for each test.
const func = await validate({
// Reset the validation function.
await validate({
shaclPath,
incoming,
outgoing,
report,
});
func();
});

test("successful", async () => {
Expand Down Expand Up @@ -104,14 +102,14 @@ describe("shacl - config", () => {
test("mime", async () => {
expect.assertions(2);

const func = await validate({
const func = validate({
shaclPath,
incoming,
outgoing,
report,
mime: "application/n-triples",
});
func();
await func;

await incoming.push(validNTriples);
await endAll();
Expand Down

0 comments on commit acfc3b8

Please sign in to comment.