Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented non-RDF fetch #104

Merged
merged 11 commits into from
Jun 3, 2020
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ First release! What's possible with this first release:
- Read data from datasets.
- Manipulate data in datasets.
- Inspect a user's permissions w.r.t. a given Resource. (Experimental.)
- Retrieve any file (including non-RDF) from a Pod.
2 changes: 2 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
fetchFile,
fetchLitDataset,
saveLitDatasetAt,
saveLitDatasetInContainer,
Expand Down Expand Up @@ -66,6 +67,7 @@ import {
// These tests aren't too useful in preventing bugs, but they work around this issue:
// https://github.com/facebook/jest/issues/10032
it("exports the public API from the entry file", () => {
expect(fetchFile).toBeDefined();
expect(fetchLitDataset).toBeDefined();
expect(saveLitDatasetAt).toBeDefined();
expect(saveLitDatasetInContainer).toBeDefined();
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DatasetCore, Quad, NamedNode, BlankNode } from "rdf-js";

export { fetchFile } from "./nonRdfData";
export {
fetchLitDataset,
saveLitDatasetAt,
Expand Down
105 changes: 105 additions & 0 deletions src/nonRdfData.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { describe, it, expect } from "@jest/globals";

jest.mock("./fetcher", () => ({
fetch: jest
.fn()
.mockImplementation(() =>
Promise.resolve(
new Response("Some data", { status: 200, statusText: "OK" })
)
),
}));

import { fetchFile } from "./nonRdfData";
import { Headers, Response } from "cross-fetch";

describe("Non-RDF data fetch", () => {
it("should GET a remote resource using cross-fetch if no other fetcher is available", async () => {
const fetcher = jest.requireMock("./fetcher") as {
fetch: jest.Mock<
ReturnType<typeof window.fetch>,
[RequestInfo, RequestInit?]
>;
};

fetcher.fetch.mockReturnValue(
Promise.resolve(
new Response("Some data", { status: 200, statusText: "OK" })
)
);

const response = await fetchFile("https://some.url");

expect(fetcher.fetch.mock.calls).toEqual([["https://some.url", undefined]]);
expect(response).toEqual(
new Response("Some data", { status: 200, statusText: "OK" })
);
});

it("should GET a remote resource using the provided fetcher", async () => {
const mockFetch = jest
.fn(window.fetch)
.mockReturnValue(
Promise.resolve(
new Response("Some data", { status: 200, statusText: "OK" })
)
);

const response = await fetchFile("https://some.url", {
fetch: mockFetch,
});

expect(mockFetch.mock.calls).toEqual([["https://some.url", undefined]]);
expect(response).toEqual(
new Response("Some data", { status: 200, statusText: "OK" })
);
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should also have a test that checks that the Response is actually returned to the caller?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ee40efb

it("should pass the request headers through", async () => {
NSeydoux marked this conversation as resolved.
Show resolved Hide resolved
const mockFetch = jest
.fn(window.fetch)
.mockReturnValue(
Promise.resolve(
new Response("Some data", { status: 200, statusText: "OK" })
)
);

const response = await fetchFile("https://some.url", {
init: {
headers: new Headers({ Accept: "text/turtle" }),
},
fetch: mockFetch,
});

expect(mockFetch.mock.calls).toEqual([
[
"https://some.url",
{
headers: new Headers({ Accept: "text/turtle" }),
},
],
]);
expect(response).toEqual(
new Response("Some data", { status: 200, statusText: "OK" })
);
});

it("should return the response even on failure", async () => {
const mockFetch = jest
.fn(window.fetch)
.mockReturnValue(
Promise.resolve(
new Response(undefined, { status: 400, statusText: "Bad request" })
)
);

const response = await fetchFile("https://some.url", {
fetch: mockFetch,
});

expect(mockFetch.mock.calls).toEqual([["https://some.url", undefined]]);
expect(response).toEqual(
new Response(undefined, { status: 400, statusText: "Bad request" })
);
});
});
27 changes: 27 additions & 0 deletions src/nonRdfData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { fetch } from "./fetcher";

interface GetFileOptions {
fetch: typeof window.fetch;
init: RequestInit;
}

const defaultGetFileOptions = {
fetch: fetch,
};

/**
* getFile fetches a file, and returns it as a blob of data.
*
* @param url The IRI of the fetched file
* @param options Fetching options: a custom fetcher and/or headers.
*/
export async function fetchFile(
input: RequestInfo,
options: Partial<GetFileOptions> = defaultGetFileOptions
): Promise<Response> {
const config = {
...defaultGetFileOptions,
...options,
};
return config.fetch(input, config.init);
}