import { Readable } from 'stream'; import type { Quad } from '@rdfjs/types'; import arrayifyStream from 'arrayify-stream'; import type { Response } from 'cross-fetch'; import { DataFactory } from 'n3'; import rdfDereferencer from 'rdf-dereference'; import { RdfToQuadConverter } from '../../../src/storage/conversion/RdfToQuadConverter'; import { fetchDataset, responseToDataset } from '../../../src/util/FetchUtil'; const { namedNode, quad } = DataFactory; jest.mock('rdf-dereference', (): any => ({ dereference: jest.fn(), })); describe('FetchUtil', (): void => { const url = 'http://test.com/foo'; function mockResponse(body: string, contentType: string | null, status = 200): Response { return ({ text: (): any => body, url, status, headers: { get: (): any => contentType }, }) as any; } describe('#fetchDataset', (): void => { const rdfDereferenceMock: jest.Mocked = rdfDereferencer as any; function mockDereference(quads?: Quad[]): any { rdfDereferenceMock.dereference.mockImplementation((uri: string): any => { if (!quads) { throw new Error('Throws error because url does not exist'); } return { uri, quads: Readable.from(quads), exists: true, }; }); } it('errors if the URL does not exist.', async(): Promise => { mockDereference(); await expect(fetchDataset(url)).rejects.toThrow(`Could not parse resource at URL (${url})!`); expect(rdfDereferenceMock.dereference).toHaveBeenCalledWith(url); }); it('returns a Representation with quads.', async(): Promise => { const quads = [ quad(namedNode('http://test.com/s'), namedNode('http://test.com/p'), namedNode('http://test.com/o')) ]; mockDereference(quads); const representation = await fetchDataset(url); await expect(arrayifyStream(representation.data)).resolves.toEqual([ quad(namedNode('http://test.com/s'), namedNode('http://test.com/p'), namedNode('http://test.com/o')), ]); }); }); describe('#responseToDataset', (): void => { const converter = new RdfToQuadConverter(); it('accepts Response objects as input.', async(): Promise => { const response = mockResponse(' .', 'text/turtle'); const body = await response.text(); const representation = await responseToDataset(response, converter, body); await expect(arrayifyStream(representation.data)).resolves.toEqual([ quad(namedNode('http://test.com/s'), namedNode('http://test.com/p'), namedNode('http://test.com/o')), ]); }); it('errors if the status code is not 200.', async(): Promise => { const response = mockResponse('Incorrect status!', null, 400); await expect(responseToDataset(response, converter)).rejects.toThrow(`Unable to access data at ${url}`); }); it('errors if there is no content-type.', async(): Promise => { const response = mockResponse('No content-type!', null); await expect(responseToDataset(response, converter)).rejects.toThrow(`Unable to access data at ${url}`); }); }); });