import 'jest-rdf'; import * as url from 'url'; import { namedNode, quad } from '@rdfjs/data-model'; import { Parser } from 'n3'; import type { MockResponse } from 'node-mocks-http'; import type { HttpHandler } from '../../src/server/HttpHandler'; import { LDP } from '../../src/util/Vocabularies'; import { performRequest } from '../util/Util'; import { BASE, instantiateFromConfig } from './Config'; describe('An integrated AuthenticatedLdpHandler', (): void => { let handler: HttpHandler; beforeAll(async(): Promise => { handler = await instantiateFromConfig( 'urn:solid-server:default:LdpHandler', 'server-without-auth.json', { 'urn:solid-server:default:variable:baseUrl': BASE, }, ) as HttpHandler; // The tests depend on there being a root container here await performRequest( handler, new URL('http://test.com/'), 'PUT', { 'content-type': 'text/turtle', 'transfer-encoding': 'chunked' }, [ ], ); }); it('can add, read and delete data based on incoming requests.', async(): Promise => { // POST let requestUrl = new URL('http://test.com/'); let response: MockResponse = await performRequest( handler, requestUrl, 'POST', { 'content-type': 'text/turtle', 'transfer-encoding': 'chunked' }, [ ' .' ], ); expect(response.statusCode).toBe(201); expect(response._getData()).toHaveLength(0); const id = response._getHeaders().location; expect(id).toContain(url.format(requestUrl)); // GET requestUrl = new URL(id); response = await performRequest( handler, requestUrl, 'GET', { accept: 'text/turtle' }, [], ); expect(response.statusCode).toBe(200); expect(response._getData()).toContain( ' .', ); expect(response.getHeaders().link).toContain(`<${LDP.Resource}>; rel="type"`); expect(response.getHeaders().link).toContain(`<${id}.acl>; rel="acl"`); // DELETE response = await performRequest(handler, requestUrl, 'DELETE', {}, []); expect(response.statusCode).toBe(205); expect(response._getData()).toHaveLength(0); // GET response = await performRequest( handler, requestUrl, 'GET', { accept: 'text/turtle' }, [], ); expect(response.statusCode).toBe(404); expect(response._getData()).toContain('NotFoundHttpError'); }); it('can handle simple SPARQL updates.', async(): Promise => { // POST let requestUrl = new URL('http://test.com/'); let response: MockResponse = await performRequest( handler, requestUrl, 'POST', { 'content-type': 'text/turtle', 'transfer-encoding': 'chunked' }, [ ' .', ' .' ], ); expect(response.statusCode).toBe(201); expect(response._getData()).toHaveLength(0); const id = response._getHeaders().location; expect(id).toContain(url.format(requestUrl)); // PATCH requestUrl = new URL(id); response = await performRequest( handler, requestUrl, 'PATCH', { 'content-type': 'application/sparql-update', 'transfer-encoding': 'chunked' }, [ 'DELETE { }', 'INSERT { }', 'WHERE {}', ], ); expect(response.statusCode).toBe(205); expect(response._getData()).toHaveLength(0); // GET response = await performRequest(handler, requestUrl, 'GET', { accept: 'text/turtle' }, []); expect(response.statusCode).toBe(200); expect(response._getData()).toContain( ' .', ); expect(response.getHeaders().link).toContain(`<${LDP.Resource}>; rel="type"`); expect(response.getHeaders().link).toContain(`<${id}.acl>; rel="acl"`); const parser = new Parser(); let triples = parser.parse(response._getData()); expect(triples).toBeRdfIsomorphic([ quad( namedNode('http://test.com/s2'), namedNode('http://test.com/p2'), namedNode('http://test.com/o2'), ), quad( namedNode('http://test.com/s3'), namedNode('http://test.com/p3'), namedNode('http://test.com/o3'), ), ]); // PATCH response = await performRequest( handler, requestUrl, 'PATCH', { 'content-type': 'application/sparql-update', 'transfer-encoding': 'chunked' }, [ 'DELETE DATA { }; ', 'INSERT DATA { }', ], ); expect(response.statusCode).toBe(205); expect(response._getData()).toHaveLength(0); // GET response = await performRequest(handler, requestUrl, 'GET', { accept: 'text/turtle' }, []); expect(response.statusCode).toBe(200); triples = parser.parse(response._getData()); expect(triples).toBeRdfIsomorphic([ quad( namedNode('http://test.com/s3'), namedNode('http://test.com/p3'), namedNode('http://test.com/o3'), ), quad( namedNode('http://test.com/s4'), namedNode('http://test.com/p4'), namedNode('http://test.com/o4'), ), ]); }); it('should overwrite the content on PUT request.', async(): Promise => { // POST let requestUrl = new URL('http://test.com/'); let response: MockResponse = await performRequest( handler, requestUrl, 'POST', { 'content-type': 'text/turtle', 'transfer-encoding': 'chunked' }, [ ' .', ' .', ], ); expect(response.statusCode).toBe(201); expect(response._getData()).toHaveLength(0); const id = response._getHeaders().location; expect(id).toContain(url.format(requestUrl)); // PUT requestUrl = new URL(id); response = await performRequest( handler, requestUrl, 'PUT', { 'content-type': 'text/turtle', 'transfer-encoding': 'chunked' }, [ ' .' ], ); expect(response.statusCode).toBe(205); expect(response._getData()).toHaveLength(0); // GET requestUrl = new URL(id); response = await performRequest( handler, requestUrl, 'GET', { accept: 'text/turtle' }, [], ); expect(response.statusCode).toBe(200); expect(response.getHeaders().link).toContain(`<${LDP.Resource}>; rel="type"`); expect(response.getHeaders().link).toContain(`<${id}.acl>; rel="acl"`); const parser = new Parser(); const triples = parser.parse(response._getData()); expect(triples).toBeRdfIsomorphic([ quad( namedNode('http://test.com/s3'), namedNode('http://test.com/p3'), namedNode('http://test.com/o3'), ), ]); }); });