mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
fix: Set max-len to 120
This commit is contained in:
parent
dcff424f58
commit
aaba113563
@ -19,6 +19,7 @@ module.exports = {
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'dot-location': ['error', 'property'],
|
||||
'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }],
|
||||
'max-len': ['error', { code: 120, ignoreUrls: true }],
|
||||
'no-underscore-dangle': 'off', // conflicts with external libraries
|
||||
'padding-line-between-statements': 'off',
|
||||
'tsdoc/syntax': 'error',
|
||||
|
@ -25,14 +25,15 @@ export class AcceptPreferenceParser extends PreferenceParser {
|
||||
|
||||
public async handle(input: HttpRequest): Promise<RepresentationPreferences> {
|
||||
const result: RepresentationPreferences = {};
|
||||
const headers: { [T in keyof RepresentationPreferences]: { val?: string; func: (input: string) => AcceptHeader[] }} = {
|
||||
const headers:
|
||||
{ [T in keyof RepresentationPreferences]: { val?: string; func: (input: string) => AcceptHeader[] }} = {
|
||||
type: { val: input.headers.accept, func: parseAccept },
|
||||
charset: { val: input.headers['accept-charset'] as string, func: parseAcceptCharset },
|
||||
encoding: { val: input.headers['accept-encoding'] as string, func: parseAcceptEncoding },
|
||||
language: { val: input.headers['accept-language'], func: parseAcceptLanguage },
|
||||
};
|
||||
(Object.keys(headers) as (keyof RepresentationPreferences)[]).forEach((key): void => {
|
||||
const preferences = this.parseHeader(headers[key]!.val, headers[key]!.func);
|
||||
const preferences = this.parseHeader(headers[key]!.func, headers[key]!.val);
|
||||
if (preferences.length > 0) {
|
||||
result[key] = preferences;
|
||||
}
|
||||
@ -53,10 +54,11 @@ export class AcceptPreferenceParser extends PreferenceParser {
|
||||
*
|
||||
* @returns A list of {@link RepresentationPreference}. Returns an empty list if input was not defined.
|
||||
*/
|
||||
private parseHeader(input: string | undefined, parseFunction: (input: string) => AcceptHeader[]): RepresentationPreference[] {
|
||||
private parseHeader(parseFunction: (input: string) => AcceptHeader[], input?: string): RepresentationPreference[] {
|
||||
if (!input) {
|
||||
return [];
|
||||
}
|
||||
return parseFunction(input).map((accept): RepresentationPreference => ({ value: accept.range, weight: accept.weight }));
|
||||
return parseFunction(input).map((accept): RepresentationPreference =>
|
||||
({ value: accept.range, weight: accept.weight }));
|
||||
}
|
||||
}
|
||||
|
@ -6,4 +6,5 @@ import { ResponseDescription } from '../operations/ResponseDescription';
|
||||
* Writes to the HttpResponse.
|
||||
* Response depends on the operation result and potentially which errors was thrown.
|
||||
*/
|
||||
export abstract class ResponseWriter extends AsyncHandler<{ response: HttpResponse; result: ResponseDescription | Error }> {}
|
||||
export abstract class ResponseWriter
|
||||
extends AsyncHandler<{ response: HttpResponse; result: ResponseDescription | Error }> {}
|
||||
|
@ -20,24 +20,31 @@ export class LockingResourceStore implements AtomicResourceStore {
|
||||
this.locks = locks;
|
||||
}
|
||||
|
||||
public async addResource(container: ResourceIdentifier, representation: Representation, conditions?: Conditions): Promise<ResourceIdentifier> {
|
||||
return this.lockedRun(container, async(): Promise<ResourceIdentifier> => this.source.addResource(container, representation, conditions));
|
||||
public async addResource(container: ResourceIdentifier, representation: Representation,
|
||||
conditions?: Conditions): Promise<ResourceIdentifier> {
|
||||
return this.lockedRun(container,
|
||||
async(): Promise<ResourceIdentifier> => this.source.addResource(container, representation, conditions));
|
||||
}
|
||||
|
||||
public async deleteResource(identifier: ResourceIdentifier, conditions?: Conditions): Promise<void> {
|
||||
return this.lockedRun(identifier, async(): Promise<void> => this.source.deleteResource(identifier, conditions));
|
||||
}
|
||||
|
||||
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences, conditions?: Conditions): Promise<Representation> {
|
||||
return this.lockedRun(identifier, async(): Promise<Representation> => this.source.getRepresentation(identifier, preferences, conditions));
|
||||
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences,
|
||||
conditions?: Conditions): Promise<Representation> {
|
||||
return this.lockedRun(identifier,
|
||||
async(): Promise<Representation> => this.source.getRepresentation(identifier, preferences, conditions));
|
||||
}
|
||||
|
||||
public async modifyResource(identifier: ResourceIdentifier, patch: Patch, conditions?: Conditions): Promise<void> {
|
||||
return this.lockedRun(identifier, async(): Promise<void> => this.source.modifyResource(identifier, patch, conditions));
|
||||
return this.lockedRun(identifier,
|
||||
async(): Promise<void> => this.source.modifyResource(identifier, patch, conditions));
|
||||
}
|
||||
|
||||
public async setRepresentation(identifier: ResourceIdentifier, representation: Representation, conditions?: Conditions): Promise<void> {
|
||||
return this.lockedRun(identifier, async(): Promise<void> => this.source.setRepresentation(identifier, representation, conditions));
|
||||
public async setRepresentation(identifier: ResourceIdentifier, representation: Representation,
|
||||
conditions?: Conditions): Promise<void> {
|
||||
return this.lockedRun(identifier,
|
||||
async(): Promise<void> => this.source.setRepresentation(identifier, representation, conditions));
|
||||
}
|
||||
|
||||
private async lockedRun<T>(identifier: ResourceIdentifier, func: () => Promise<T>): Promise<T> {
|
||||
|
@ -20,7 +20,8 @@ export class PatchingStore implements ResourceStore {
|
||||
this.patcher = patcher;
|
||||
}
|
||||
|
||||
public async addResource(container: ResourceIdentifier, representation: Representation, conditions?: Conditions): Promise<ResourceIdentifier> {
|
||||
public async addResource(container: ResourceIdentifier, representation: Representation,
|
||||
conditions?: Conditions): Promise<ResourceIdentifier> {
|
||||
return this.source.addResource(container, representation, conditions);
|
||||
}
|
||||
|
||||
@ -28,11 +29,13 @@ export class PatchingStore implements ResourceStore {
|
||||
return this.source.deleteResource(identifier, conditions);
|
||||
}
|
||||
|
||||
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences, conditions?: Conditions): Promise<Representation> {
|
||||
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences,
|
||||
conditions?: Conditions): Promise<Representation> {
|
||||
return this.source.getRepresentation(identifier, preferences, conditions);
|
||||
}
|
||||
|
||||
public async setRepresentation(identifier: ResourceIdentifier, representation: Representation, conditions?: Conditions): Promise<void> {
|
||||
public async setRepresentation(identifier: ResourceIdentifier, representation: Representation,
|
||||
conditions?: Conditions): Promise<void> {
|
||||
return this.source.setRepresentation(identifier, representation, conditions);
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,8 @@ export class SimpleResourceStore implements ResourceStore {
|
||||
*
|
||||
* @returns The corresponding Representation.
|
||||
*/
|
||||
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences): Promise<Representation> {
|
||||
public async getRepresentation(identifier: ResourceIdentifier,
|
||||
preferences: RepresentationPreferences): Promise<Representation> {
|
||||
const path = this.parseIdentifier(identifier);
|
||||
return this.generateRepresentation(this.store[path], preferences);
|
||||
}
|
||||
|
@ -48,12 +48,14 @@ export class SimpleSparqlUpdatePatchHandler extends PatchHandler {
|
||||
if (!inserts.every((pattern): boolean => pattern.graph.equals(def))) {
|
||||
throw new UnsupportedHttpError('GRAPH statements are not supported.');
|
||||
}
|
||||
if (op.where ?? deletes.some((pattern): boolean => someTerms(pattern, (term): boolean => term.termType === 'Variable'))) {
|
||||
if (op.where ?? deletes.some((pattern): boolean =>
|
||||
someTerms(pattern, (term): boolean => term.termType === 'Variable'))) {
|
||||
throw new UnsupportedHttpError('WHERE statements are not supported.');
|
||||
}
|
||||
|
||||
const lock = await this.locker.acquire(input.identifier);
|
||||
const quads = await this.source.getRepresentation(input.identifier, { type: [{ value: 'internal/quads', weight: 1 }]});
|
||||
const quads = await this.source.getRepresentation(input.identifier,
|
||||
{ type: [{ value: 'internal/quads', weight: 1 }]});
|
||||
const store = new Store<BaseQuad>();
|
||||
const importEmitter = store.import(quads.data);
|
||||
await new Promise((resolve, reject): void => {
|
||||
|
@ -38,7 +38,8 @@ import { UnsupportedHttpError } from './errors/UnsupportedHttpError';
|
||||
// language-range = (1*8ALPHA *("-" 1*8alphanum)) / "*"
|
||||
// alphanum = ALPHA / DIGIT
|
||||
//
|
||||
// Delimiters are chosen from the set of US-ASCII visual characters not allowed in a token (DQUOTE and "(),/:;<=>?@[\]{}").
|
||||
// Delimiters are chosen from the set of US-ASCII visual characters
|
||||
// not allowed in a token (DQUOTE and "(),/:;<=>?@[\]{}").
|
||||
// token = 1*tchar
|
||||
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
|
||||
// / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
|
||||
@ -65,7 +66,10 @@ export interface Accept extends AcceptHeader {
|
||||
parameters: {
|
||||
/** Media type parameters. These are the parameters that came before the q value. */
|
||||
mediaType: { [key: string]: string };
|
||||
/** Extension parameters. These are the parameters that came after the q value. Value will be an empty string if there was none. */
|
||||
/**
|
||||
* Extension parameters. These are the parameters that came after the q value.
|
||||
* Value will be an empty string if there was none.
|
||||
*/
|
||||
extension: { [key: string]: string };
|
||||
};
|
||||
}
|
||||
@ -101,7 +105,9 @@ const transformQuotedStrings = (input: string): { result: string; replacements:
|
||||
const result = input.replace(/"(?:[^"\\]|\\.)*"/gu, (match): string => {
|
||||
// Not all characters allowed in quoted strings, see BNF above
|
||||
if (!/^"(?:[\t !\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|(?:\\[\t\u0020-\u007e\u0080-\u00ff]))*"$/u.test(match)) {
|
||||
throw new UnsupportedHttpError(`Invalid quoted string in Accept header: ${match}. Check which characters are allowed`);
|
||||
throw new UnsupportedHttpError(
|
||||
`Invalid quoted string in Accept header: ${match}. Check which characters are allowed`,
|
||||
);
|
||||
}
|
||||
const replacement = `"${idx}"`;
|
||||
replacements[replacement] = match;
|
||||
@ -131,7 +137,9 @@ const splitAndClean = (input: string): string[] =>
|
||||
*/
|
||||
const testQValue = (qvalue: string): void => {
|
||||
if (!/^q=(?:(?:0(?:\.\d{0,3})?)|(?:1(?:\.0{0,3})?))$/u.test(qvalue)) {
|
||||
throw new UnsupportedHttpError(`Invalid q value: ${qvalue} does not match ("q=" ( "0" [ "." 0*3DIGIT ] ) / ( "1" [ "." 0*3("0") ] )).`);
|
||||
throw new UnsupportedHttpError(
|
||||
`Invalid q value: ${qvalue} does not match ("q=" ( "0" [ "." 0*3DIGIT ] ) / ( "1" [ "." 0*3("0") ] )).`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -155,7 +163,9 @@ const parseAcceptPart = (part: string, replacements: { [id: string]: string }):
|
||||
// No reason to test differently for * since we don't check if the type exists
|
||||
const [ type, subtype ] = range.split('/');
|
||||
if (!type || !subtype || !token.test(type) || !token.test(subtype)) {
|
||||
throw new Error(`Invalid Accept range: ${range} does not match ( "*/*" / ( token "/" "*" ) / ( token "/" token ) )`);
|
||||
throw new Error(
|
||||
`Invalid Accept range: ${range} does not match ( "*/*" / ( token "/" "*" ) / ( token "/" token ) )`,
|
||||
);
|
||||
}
|
||||
|
||||
let weight = 1;
|
||||
@ -174,9 +184,12 @@ const parseAcceptPart = (part: string, replacements: { [id: string]: string }):
|
||||
// Test replaced string for easier check
|
||||
// parameter = token "=" ( token / quoted-string )
|
||||
// second part is optional for extension parameters
|
||||
if (!token.test(name) || !((map === extensionParams && !value) || (value && (/^"\d+"$/u.test(value) || token.test(value))))) {
|
||||
throw new UnsupportedHttpError(`Invalid Accept parameter: ${param} does not match (token "=" ( token / quoted-string )). ` +
|
||||
'Second part optional for extension parameters.');
|
||||
if (!token.test(name) ||
|
||||
!((map === extensionParams && !value) || (value && (/^"\d+"$/u.test(value) || token.test(value))))) {
|
||||
throw new UnsupportedHttpError(
|
||||
`Invalid Accept parameter: ${param} does not match (token "=" ( token / quoted-string )). ` +
|
||||
`Second part is optional for extension parameters.`,
|
||||
);
|
||||
}
|
||||
|
||||
let actualValue = value;
|
||||
@ -256,7 +269,9 @@ export const parseAcceptCharset = (input: string): AcceptCharset[] => {
|
||||
const results = parseNoParameters(input);
|
||||
results.forEach((result): void => {
|
||||
if (!token.test(result.range)) {
|
||||
throw new UnsupportedHttpError(`Invalid Accept-Charset range: ${result.range} does not match (content-coding / "identity" / "*")`);
|
||||
throw new UnsupportedHttpError(
|
||||
`Invalid Accept-Charset range: ${result.range} does not match (content-coding / "identity" / "*")`,
|
||||
);
|
||||
}
|
||||
});
|
||||
return results;
|
||||
@ -297,7 +312,9 @@ export const parseAcceptLanguage = (input: string): AcceptLanguage[] => {
|
||||
results.forEach((result): void => {
|
||||
// (1*8ALPHA *("-" 1*8alphanum)) / "*"
|
||||
if (result.range !== '*' && !/^[a-zA-Z]{1,8}(?:-[a-zA-Z0-9]{1,8})*$/u.test(result.range)) {
|
||||
throw new UnsupportedHttpError(`Invalid Accept-Language range: ${result.range} does not match ((1*8ALPHA *("-" 1*8alphanum)) / "*")`);
|
||||
throw new UnsupportedHttpError(
|
||||
`Invalid Accept-Language range: ${result.range} does not match ((1*8ALPHA *("-" 1*8alphanum)) / "*")`,
|
||||
);
|
||||
}
|
||||
});
|
||||
return results;
|
||||
|
@ -46,7 +46,8 @@ export class CompositeAsyncHandler<TIn, TOut> implements AsyncHandler<TIn, TOut>
|
||||
}
|
||||
|
||||
/**
|
||||
* Identical to {@link AsyncHandler.handleSafe} but optimized for composite by only needing 1 canHandle call on members.
|
||||
* Identical to {@link AsyncHandler.handleSafe} but optimized for composite
|
||||
* by only needing 1 canHandle call on members.
|
||||
* @param input - The input data.
|
||||
*
|
||||
* @returns A promise corresponding to the handle call of a handler that supports the input.
|
||||
|
@ -31,7 +31,8 @@ import { createResponse, MockResponse } from 'node-mocks-http';
|
||||
import { namedNode, quad } from '@rdfjs/data-model';
|
||||
import * as url from 'url';
|
||||
|
||||
const call = async(handler: HttpHandler, requestUrl: url.URL, method: string, headers: IncomingHttpHeaders, data: string[]): Promise<MockResponse<any>> => {
|
||||
const call = async(handler: HttpHandler, requestUrl: url.URL, method: string,
|
||||
headers: IncomingHttpHeaders, data: string[]): Promise<MockResponse<any>> => {
|
||||
const request = streamifyArray(data) as HttpRequest;
|
||||
request.url = requestUrl.pathname;
|
||||
request.method = method;
|
||||
|
@ -39,7 +39,9 @@ describe('An AuthenticatedLdpHandler', (): void => {
|
||||
it('can check if it handles input.', async(): Promise<void> => {
|
||||
const handler = new AuthenticatedLdpHandler(args);
|
||||
|
||||
await expect(handler.canHandle({ request: {} as HttpRequest, response: {} as HttpResponse })).resolves.toBeUndefined();
|
||||
await expect(handler.canHandle(
|
||||
{ request: {} as HttpRequest, response: {} as HttpResponse },
|
||||
)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('can handle input.', async(): Promise<void> => {
|
||||
|
@ -18,22 +18,29 @@ describe('An AcceptPreferenceParser', (): void => {
|
||||
});
|
||||
|
||||
it('parses accept-charset headers.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle({ headers: { 'accept-charset': 'iso-8859-5, unicode-1-1;q=0.8' }} as unknown as HttpRequest))
|
||||
.resolves.toEqual({ charset: [{ value: 'iso-8859-5', weight: 1 }, { value: 'unicode-1-1', weight: 0.8 }]});
|
||||
await expect(preferenceParser.handle(
|
||||
{ headers: { 'accept-charset': 'iso-8859-5, unicode-1-1;q=0.8' }} as unknown as HttpRequest,
|
||||
)).resolves.toEqual({ charset: [{ value: 'iso-8859-5', weight: 1 }, { value: 'unicode-1-1', weight: 0.8 }]});
|
||||
});
|
||||
|
||||
it('parses accept-datetime headers.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle({ headers: { 'accept-datetime': 'Tue, 20 Mar 2001 20:35:00 GMT' }} as unknown as HttpRequest))
|
||||
.resolves.toEqual({ datetime: [{ value: 'Tue, 20 Mar 2001 20:35:00 GMT', weight: 1 }]});
|
||||
await expect(preferenceParser.handle(
|
||||
{ headers: { 'accept-datetime': 'Tue, 20 Mar 2001 20:35:00 GMT' }} as unknown as HttpRequest,
|
||||
)).resolves.toEqual({ datetime: [{ value: 'Tue, 20 Mar 2001 20:35:00 GMT', weight: 1 }]});
|
||||
});
|
||||
|
||||
it('parses accept-encoding headers.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle({ headers: { 'accept-encoding': 'gzip;q=1.0, identity; q=0.5, *;q=0' }} as unknown as HttpRequest))
|
||||
.resolves.toEqual({ encoding: [{ value: 'gzip', weight: 1 }, { value: 'identity', weight: 0.5 }, { value: '*', weight: 0 }]});
|
||||
await expect(preferenceParser.handle(
|
||||
{ headers: { 'accept-encoding': 'gzip;q=1.0, identity; q=0.5, *;q=0' }} as unknown as HttpRequest,
|
||||
)).resolves.toEqual(
|
||||
{ encoding: [{ value: 'gzip', weight: 1 }, { value: 'identity', weight: 0.5 }, { value: '*', weight: 0 }]},
|
||||
);
|
||||
});
|
||||
|
||||
it('parses accept-language headers.', async(): Promise<void> => {
|
||||
await expect(preferenceParser.handle({ headers: { 'accept-language': 'da, en-gb;q=0.8, en;q=0.7' }} as HttpRequest))
|
||||
.resolves.toEqual({ language: [{ value: 'da', weight: 1 }, { value: 'en-gb', weight: 0.8 }, { value: 'en', weight: 0.7 }]});
|
||||
.resolves.toEqual(
|
||||
{ language: [{ value: 'da', weight: 1 }, { value: 'en-gb', weight: 0.8 }, { value: 'en', weight: 0.7 }]},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -15,9 +15,12 @@ describe('A SimpleResponseWriter', (): void => {
|
||||
});
|
||||
|
||||
it('requires the description body to be a string or binary stream if present.', async(): Promise<void> => {
|
||||
await expect(writer.canHandle({ response, result: { body: { dataType: 'quad' }} as ResponseDescription })).rejects.toThrow(UnsupportedHttpError);
|
||||
await expect(writer.canHandle({ response, result: { body: { dataType: 'string' }} as ResponseDescription })).resolves.toBeUndefined();
|
||||
await expect(writer.canHandle({ response, result: { body: { dataType: 'binary' }} as ResponseDescription })).resolves.toBeUndefined();
|
||||
await expect(writer.canHandle({ response, result: { body: { dataType: 'quad' }} as ResponseDescription }))
|
||||
.rejects.toThrow(UnsupportedHttpError);
|
||||
await expect(writer.canHandle({ response, result: { body: { dataType: 'string' }} as ResponseDescription }))
|
||||
.resolves.toBeUndefined();
|
||||
await expect(writer.canHandle({ response, result: { body: { dataType: 'binary' }} as ResponseDescription }))
|
||||
.resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('responds with status code 200 and a location header if there is a description.', async(): Promise<void> => {
|
||||
|
@ -11,12 +11,15 @@ describe('A SimpleSparqlUpdateBodyParser', (): void => {
|
||||
|
||||
it('only accepts application/sparql-update content.', async(): Promise<void> => {
|
||||
await expect(bodyParser.canHandle({ headers: {}} as HttpRequest)).rejects.toThrow(UnsupportedMediaTypeHttpError);
|
||||
await expect(bodyParser.canHandle({ headers: { 'content-type': 'text/plain' }} as HttpRequest)).rejects.toThrow(UnsupportedMediaTypeHttpError);
|
||||
await expect(bodyParser.canHandle({ headers: { 'content-type': 'application/sparql-update' }} as HttpRequest)).resolves.toBeUndefined();
|
||||
await expect(bodyParser.canHandle({ headers: { 'content-type': 'text/plain' }} as HttpRequest))
|
||||
.rejects.toThrow(UnsupportedMediaTypeHttpError);
|
||||
await expect(bodyParser.canHandle({ headers: { 'content-type': 'application/sparql-update' }} as HttpRequest))
|
||||
.resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('errors when handling invalid SPARQL updates.', async(): Promise<void> => {
|
||||
await expect(bodyParser.handle(streamifyArray([ 'VERY INVALID UPDATE' ]) as HttpRequest)).rejects.toThrow(UnsupportedHttpError);
|
||||
await expect(bodyParser.handle(streamifyArray([ 'VERY INVALID UPDATE' ]) as HttpRequest))
|
||||
.rejects.toThrow(UnsupportedHttpError);
|
||||
});
|
||||
|
||||
it('converts SPARQL updates to algebra.', async(): Promise<void> => {
|
||||
|
@ -16,7 +16,8 @@ describe('A SimpleTargetExtractor', (): void => {
|
||||
});
|
||||
|
||||
it('uses https protocol if the connection is secure.', async(): Promise<void> => {
|
||||
await expect(extractor.handle({ url: 'url', headers: { host: 'test.com' }, connection: { encrypted: true } as any } as any))
|
||||
.resolves.toEqual({ path: 'https://test.com/url' });
|
||||
await expect(extractor.handle(
|
||||
{ url: 'url', headers: { host: 'test.com' }, connection: { encrypted: true } as any } as any,
|
||||
)).resolves.toEqual({ path: 'https://test.com/url' });
|
||||
});
|
||||
});
|
||||
|
@ -17,7 +17,8 @@ describe('A SimpleDeleteOperationHandler', (): void => {
|
||||
});
|
||||
|
||||
it('deletes the resource from the store and returns its identifier.', async(): Promise<void> => {
|
||||
await expect(handler.handle({ target: { path: 'url' }} as Operation)).resolves.toEqual({ identifier: { path: 'url' }});
|
||||
await expect(handler.handle({ target: { path: 'url' }} as Operation))
|
||||
.resolves.toEqual({ identifier: { path: 'url' }});
|
||||
expect(store.deleteResource).toHaveBeenCalledTimes(1);
|
||||
expect(store.deleteResource).toHaveBeenLastCalledWith({ path: 'url' });
|
||||
});
|
||||
|
@ -11,8 +11,10 @@ describe('A SimplePostOperationHandler', (): void => {
|
||||
const handler = new SimplePostOperationHandler(store);
|
||||
|
||||
it('only supports POST operations with a body.', async(): Promise<void> => {
|
||||
await expect(handler.canHandle({ method: 'POST', body: { dataType: 'test' }} as Operation)).resolves.toBeUndefined();
|
||||
await expect(handler.canHandle({ method: 'GET', body: { dataType: 'test' }} as Operation)).rejects.toThrow(UnsupportedHttpError);
|
||||
await expect(handler.canHandle({ method: 'POST', body: { dataType: 'test' }} as Operation))
|
||||
.resolves.toBeUndefined();
|
||||
await expect(handler.canHandle({ method: 'GET', body: { dataType: 'test' }} as Operation))
|
||||
.rejects.toThrow(UnsupportedHttpError);
|
||||
await expect(handler.canHandle({ method: 'POST' } as Operation)).rejects.toThrow(UnsupportedHttpError);
|
||||
});
|
||||
|
||||
@ -21,6 +23,7 @@ describe('A SimplePostOperationHandler', (): void => {
|
||||
});
|
||||
|
||||
it('adds the given representation to the store and returns the new identifier.', async(): Promise<void> => {
|
||||
await expect(handler.handle({ method: 'POST', body: { dataType: 'test' }} as Operation)).resolves.toEqual({ identifier: { path: 'newPath' }});
|
||||
await expect(handler.handle({ method: 'POST', body: { dataType: 'test' }} as Operation))
|
||||
.resolves.toEqual({ identifier: { path: 'newPath' }});
|
||||
});
|
||||
});
|
||||
|
@ -53,7 +53,8 @@ describe('ExpressHttpServer', (): void => {
|
||||
'access-control-allow-origin': '*',
|
||||
'access-control-allow-headers': 'content-type',
|
||||
}));
|
||||
const corsMethods = res.header['access-control-allow-methods'].split(',').map((method: string): string => method.trim());
|
||||
const corsMethods = res.header['access-control-allow-methods'].split(',')
|
||||
.map((method: string): string => method.trim());
|
||||
const allowedMethods = [ 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ];
|
||||
expect(corsMethods).toEqual(expect.arrayContaining(allowedMethods));
|
||||
expect(corsMethods.length).toBe(allowedMethods.length);
|
||||
|
@ -24,11 +24,16 @@ describe('A LockingResourceStore', (): void => {
|
||||
};
|
||||
|
||||
source = {
|
||||
getRepresentation: jest.fn(async(): Promise<any> => new Promise((resolve): any => delayedResolve(resolve, 'getRepresentation'))),
|
||||
addResource: jest.fn(async(): Promise<any> => new Promise((resolve): any => delayedResolve(resolve, 'addResource'))),
|
||||
setRepresentation: jest.fn(async(): Promise<any> => new Promise((resolve): any => delayedResolve(resolve, 'setRepresentation'))),
|
||||
deleteResource: jest.fn(async(): Promise<any> => new Promise((resolve): any => delayedResolve(resolve, 'deleteResource'))),
|
||||
modifyResource: jest.fn(async(): Promise<any> => new Promise((resolve): any => delayedResolve(resolve, 'modifyResource'))),
|
||||
getRepresentation: jest.fn(async(): Promise<any> =>
|
||||
new Promise((resolve): any => delayedResolve(resolve, 'getRepresentation'))),
|
||||
addResource: jest.fn(async(): Promise<any> =>
|
||||
new Promise((resolve): any => delayedResolve(resolve, 'addResource'))),
|
||||
setRepresentation: jest.fn(async(): Promise<any> =>
|
||||
new Promise((resolve): any => delayedResolve(resolve, 'setRepresentation'))),
|
||||
deleteResource: jest.fn(async(): Promise<any> =>
|
||||
new Promise((resolve): any => delayedResolve(resolve, 'deleteResource'))),
|
||||
modifyResource: jest.fn(async(): Promise<any> =>
|
||||
new Promise((resolve): any => delayedResolve(resolve, 'modifyResource'))),
|
||||
};
|
||||
release = jest.fn(async(): Promise<any> => order.push('release'));
|
||||
locker = {
|
||||
|
@ -31,9 +31,11 @@ describe('A SimpleResourceStore', (): void => {
|
||||
|
||||
it('errors if a resource was not found.', async(): Promise<void> => {
|
||||
await expect(store.getRepresentation({ path: `${base}wrong` }, {})).rejects.toThrow(NotFoundHttpError);
|
||||
await expect(store.addResource({ path: 'http://wrong.com/wrong' }, representation)).rejects.toThrow(NotFoundHttpError);
|
||||
await expect(store.addResource({ path: 'http://wrong.com/wrong' }, representation))
|
||||
.rejects.toThrow(NotFoundHttpError);
|
||||
await expect(store.deleteResource({ path: 'wrong' })).rejects.toThrow(NotFoundHttpError);
|
||||
await expect(store.setRepresentation({ path: 'http://wrong.com/' }, representation)).rejects.toThrow(NotFoundHttpError);
|
||||
await expect(store.setRepresentation({ path: 'http://wrong.com/' }, representation))
|
||||
.rejects.toThrow(NotFoundHttpError);
|
||||
});
|
||||
|
||||
it('errors when modifying resources.', async(): Promise<void> => {
|
||||
|
@ -63,7 +63,9 @@ describe('A SimpleSparqlUpdatePatchHandler', (): void => {
|
||||
|
||||
const basicChecks = async(quads: Quad[]): Promise<void> => {
|
||||
expect(source.getRepresentation).toHaveBeenCalledTimes(1);
|
||||
expect(source.getRepresentation).toHaveBeenLastCalledWith({ path: 'path' }, { type: [{ value: 'internal/quads', weight: 1 }]});
|
||||
expect(source.getRepresentation).toHaveBeenLastCalledWith(
|
||||
{ path: 'path' }, { type: [{ value: 'internal/quads', weight: 1 }]},
|
||||
);
|
||||
expect(source.setRepresentation).toHaveBeenCalledTimes(1);
|
||||
expect(order).toEqual([ 'acquire', 'getRepresentation', 'setRepresentation', 'release' ]);
|
||||
const setParams = (source.setRepresentation as jest.Mock).mock.calls[0];
|
||||
@ -76,7 +78,8 @@ describe('A SimpleSparqlUpdatePatchHandler', (): void => {
|
||||
};
|
||||
|
||||
it('only accepts SPARQL updates.', async(): Promise<void> => {
|
||||
const input = { identifier: { path: 'path' }, patch: { dataType: 'sparql-algebra', algebra: {}} as SparqlUpdatePatch };
|
||||
const input = { identifier: { path: 'path' },
|
||||
patch: { dataType: 'sparql-algebra', algebra: {}} as SparqlUpdatePatch };
|
||||
await expect(handler.canHandle(input)).resolves.toBeUndefined();
|
||||
input.patch.dataType = 'notAlgebra';
|
||||
await expect(handler.canHandle(input)).rejects.toThrow(UnsupportedHttpError);
|
||||
@ -102,7 +105,9 @@ describe('A SimpleSparqlUpdatePatchHandler', (): void => {
|
||||
{ quads: true },
|
||||
) } as SparqlUpdatePatch });
|
||||
await basicChecks(
|
||||
[ quad(namedNode('http://test.com/startS2'), namedNode('http://test.com/startP2'), namedNode('http://test.com/startO2')) ],
|
||||
[ quad(namedNode('http://test.com/startS2'),
|
||||
namedNode('http://test.com/startP2'),
|
||||
namedNode('http://test.com/startO2')) ],
|
||||
);
|
||||
});
|
||||
|
||||
@ -113,7 +118,9 @@ describe('A SimpleSparqlUpdatePatchHandler', (): void => {
|
||||
{ quads: true },
|
||||
) } as SparqlUpdatePatch });
|
||||
await basicChecks(
|
||||
[ quad(namedNode('http://test.com/startS2'), namedNode('http://test.com/startP2'), namedNode('http://test.com/startO2')) ],
|
||||
[ quad(namedNode('http://test.com/startS2'),
|
||||
namedNode('http://test.com/startP2'),
|
||||
namedNode('http://test.com/startO2')) ],
|
||||
);
|
||||
});
|
||||
|
||||
@ -125,16 +132,21 @@ describe('A SimpleSparqlUpdatePatchHandler', (): void => {
|
||||
'WHERE {}',
|
||||
{ quads: true },
|
||||
) } as SparqlUpdatePatch });
|
||||
await basicChecks(
|
||||
[ quad(namedNode('http://test.com/startS2'), namedNode('http://test.com/startP2'), namedNode('http://test.com/startO2')),
|
||||
quad(namedNode('http://test.com/s1'), namedNode('http://test.com/p1'), namedNode('http://test.com/o1')) ],
|
||||
);
|
||||
await basicChecks([
|
||||
quad(namedNode('http://test.com/startS2'),
|
||||
namedNode('http://test.com/startP2'),
|
||||
namedNode('http://test.com/startO2')),
|
||||
quad(namedNode('http://test.com/s1'),
|
||||
namedNode('http://test.com/p1'),
|
||||
namedNode('http://test.com/o1')),
|
||||
]);
|
||||
});
|
||||
|
||||
it('rejects GRAPH inserts.', async(): Promise<void> => {
|
||||
const handle = handler.handle({ identifier: { path: 'path' },
|
||||
patch: { algebra: translate(
|
||||
'INSERT DATA { GRAPH <http://test.com/graph> { <http://test.com/startS1> <http://test.com/startP1> <http://test.com/startO1> } }',
|
||||
'INSERT DATA { GRAPH <http://test.com/graph> { ' +
|
||||
'<http://test.com/startS1> <http://test.com/startP1> <http://test.com/startO1> } }',
|
||||
{ quads: true },
|
||||
) } as SparqlUpdatePatch });
|
||||
await expect(handle).rejects.toThrow('GRAPH statements are not supported.');
|
||||
@ -144,7 +156,8 @@ describe('A SimpleSparqlUpdatePatchHandler', (): void => {
|
||||
it('rejects GRAPH deletes.', async(): Promise<void> => {
|
||||
const handle = handler.handle({ identifier: { path: 'path' },
|
||||
patch: { algebra: translate(
|
||||
'DELETE DATA { GRAPH <http://test.com/graph> { <http://test.com/startS1> <http://test.com/startP1> <http://test.com/startO1> } }',
|
||||
'DELETE DATA { GRAPH <http://test.com/graph> { ' +
|
||||
'<http://test.com/startS1> <http://test.com/startP1> <http://test.com/startO1> } }',
|
||||
{ quads: true },
|
||||
) } as SparqlUpdatePatch });
|
||||
await expect(handle).rejects.toThrow('GRAPH statements are not supported.');
|
||||
|
@ -25,7 +25,9 @@ describe('AcceptParser', (): void => {
|
||||
});
|
||||
|
||||
it('parses complex Accept headers.', async(): Promise<void> => {
|
||||
expect(parseAccept('text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4,text/x-dvi; q=0.8; mxb=100000; mxt')).toEqual([
|
||||
expect(parseAccept(
|
||||
'text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4,text/x-dvi; q=0.8; mxb=100000; mxt',
|
||||
)).toEqual([
|
||||
{ range: 'text/html', weight: 1, parameters: { mediaType: { level: '1' }, extension: {}}},
|
||||
{ range: 'text/x-dvi', weight: 0.8, parameters: { mediaType: {}, extension: { mxb: '100000', mxt: '' }}},
|
||||
{ range: 'text/html', weight: 0.7, parameters: { mediaType: {}, extension: {}}},
|
||||
@ -35,7 +37,9 @@ describe('AcceptParser', (): void => {
|
||||
|
||||
it('parses Accept headers with double quoted values.', async(): Promise<void> => {
|
||||
expect(parseAccept('audio/basic; param1="val" ; q=0.5 ;param2="\\\\\\"valid"')).toEqual([
|
||||
{ range: 'audio/basic', weight: 0.5, parameters: { mediaType: { param1: '"val"' }, extension: { param2: '"\\\\\\"valid"' }}},
|
||||
{ range: 'audio/basic',
|
||||
weight: 0.5,
|
||||
parameters: { mediaType: { param1: '"val"' }, extension: { param2: '"\\\\\\"valid"' }}},
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -67,7 +67,7 @@ describe('A CompositeAsyncHandler', (): void => {
|
||||
expect(handleFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('throws the same error as canHandle when calling handleSafe if no handler supports the data.', async(): Promise<void> => {
|
||||
it('throws the canHandle error when calling handleSafe if the data is not supported.', async(): Promise<void> => {
|
||||
const handler = new CompositeAsyncHandler([ handlerFalse, handlerFalse ]);
|
||||
|
||||
await expect(handler.handleSafe(null)).rejects.toThrow('[Not supported., Not supported.]');
|
||||
|
Loading…
x
Reference in New Issue
Block a user