feat: Determine Typed Converter output based on input type

This commit is contained in:
Joachim Van Herwegen
2021-10-26 16:30:10 +02:00
parent 27306d6e3f
commit fa94c7d4bb
17 changed files with 107 additions and 134 deletions

View File

@@ -22,15 +22,7 @@ const logger: jest.Mocked<Logger> = getLoggerFor('GuardedStream') as any;
class DummyConverter extends BaseTypedRepresentationConverter {
public constructor() {
super('*/*', 'custom/type');
}
public async getInputTypes(): Promise<Record<string, number>> {
return { [INTERNAL_QUADS]: 1 };
}
public async getOutputTypes(): Promise<Record<string, number>> {
return { 'x/x': 1 };
super(INTERNAL_QUADS, 'x/x');
}
public async handle({ representation }: RepresentationConverterArgs): Promise<Representation> {

View File

@@ -7,56 +7,37 @@ class CustomTypedRepresentationConverter extends BaseTypedRepresentationConverte
}
describe('A BaseTypedRepresentationConverter', (): void => {
it('defaults to allowing everything.', async(): Promise<void> => {
const converter = new CustomTypedRepresentationConverter();
await expect(converter.getInputTypes()).resolves.toEqual({
});
await expect(converter.getOutputTypes()).resolves.toEqual({
});
});
it('accepts strings.', async(): Promise<void> => {
const converter = new CustomTypedRepresentationConverter('a/b', 'c/d');
await expect(converter.getInputTypes()).resolves.toEqual({
'a/b': 1,
});
await expect(converter.getOutputTypes()).resolves.toEqual({
await expect(converter.getOutputTypes('a/b')).resolves.toEqual({
'c/d': 1,
});
});
it('accepts string arrays.', async(): Promise<void> => {
const converter = new CustomTypedRepresentationConverter([ 'a/b', 'c/d' ], [ 'e/f', 'g/h' ]);
await expect(converter.getInputTypes()).resolves.toEqual({
'a/b': 1,
'c/d': 1,
});
await expect(converter.getOutputTypes()).resolves.toEqual({
'e/f': 1,
'g/h': 1,
});
const output = { 'e/f': 1, 'g/h': 1 };
await expect(converter.getOutputTypes('a/b')).resolves.toEqual(output);
await expect(converter.getOutputTypes('c/d')).resolves.toEqual(output);
});
it('accepts records.', async(): Promise<void> => {
const converter = new CustomTypedRepresentationConverter({ 'a/b': 0.5 }, { 'c/d': 0.5 });
await expect(converter.getInputTypes()).resolves.toEqual({
'a/b': 0.5,
});
await expect(converter.getOutputTypes()).resolves.toEqual({
'c/d': 0.5,
await expect(converter.getOutputTypes('a/b')).resolves.toEqual({
'c/d': 0.5 * 0.5,
});
});
it('can not handle input without a Content-Type.', async(): Promise<void> => {
const args: RepresentationConverterArgs = { representation: { metadata: { }}, preferences: {}} as any;
const converter = new CustomTypedRepresentationConverter('*/*');
const converter = new CustomTypedRepresentationConverter('*/*', 'b/b');
await expect(converter.canHandle(args)).rejects.toThrow(NotImplementedHttpError);
});
it('can not handle a type that does not match the input types.', async(): Promise<void> => {
const args: RepresentationConverterArgs =
{ representation: { metadata: { contentType: 'b/b' }}, preferences: {}} as any;
const converter = new CustomTypedRepresentationConverter('a/a');
const converter = new CustomTypedRepresentationConverter('a/a', 'b/b');
await expect(converter.canHandle(args)).rejects.toThrow(NotImplementedHttpError);
});

View File

@@ -15,19 +15,11 @@ class DummyConverter extends BaseTypedRepresentationConverter {
private readonly outTypes: ValuePreferences;
public constructor(inTypes: ValuePreferences, outTypes: ValuePreferences) {
super();
super(inTypes, outTypes);
this.inTypes = inTypes;
this.outTypes = outTypes;
}
public async getInputTypes(): Promise<ValuePreferences> {
return this.inTypes;
}
public async getOutputTypes(): Promise<ValuePreferences> {
return this.outTypes;
}
public async handle(input: RepresentationConverterArgs): Promise<Representation> {
// Make sure the input type is supported
const inType = input.representation.metadata.contentType!;

View File

@@ -6,7 +6,7 @@ import {
getTypeWeight,
getWeightedPreferences, isInternalContentType,
matchesMediaPreferences,
matchesMediaType,
matchesMediaType, preferencesToString,
} from '../../../../src/storage/conversion/ConversionUtil';
import { InternalServerError } from '../../../../src/util/errors/InternalServerError';
@@ -153,4 +153,11 @@ describe('ConversionUtil', (): void => {
expect(isInternalContentType('text/turtle')).toBeFalsy();
});
});
describe('#preferencesToString', (): void => {
it('returns a string serialization.', async(): Promise<void> => {
const preferences: ValuePreferences = { 'a/*': 1, 'b/b': 0.8, 'c/c': 0 };
expect(preferencesToString(preferences)).toEqual('a/*:1,b/b:0.8,c/c:0');
});
});
});

View File

@@ -9,8 +9,7 @@ describe('An ErrorToJsonConverter', (): void => {
const preferences = {};
it('supports going from errors to json.', async(): Promise<void> => {
await expect(converter.getInputTypes()).resolves.toEqual({ 'internal/error': 1 });
await expect(converter.getOutputTypes()).resolves.toEqual({ 'application/json': 1 });
await expect(converter.getOutputTypes('internal/error')).resolves.toEqual({ 'application/json': 1 });
});
it('adds all HttpError fields.', async(): Promise<void> => {

View File

@@ -13,8 +13,7 @@ describe('An ErrorToQuadConverter', (): void => {
const preferences = {};
it('supports going from errors to quads.', async(): Promise<void> => {
await expect(converter.getInputTypes()).resolves.toEqual({ 'internal/error': 1 });
await expect(converter.getOutputTypes()).resolves.toEqual({ 'internal/quads': 1 });
await expect(converter.getOutputTypes('internal/error')).resolves.toEqual({ 'internal/quads': 1 });
});
it('adds triples for all error fields.', async(): Promise<void> => {

View File

@@ -24,8 +24,7 @@ describe('An ErrorToTemplateConverter', (): void => {
});
it('supports going from errors to the given content type.', async(): Promise<void> => {
await expect(converter.getInputTypes()).resolves.toEqual({ 'internal/error': 1 });
await expect(converter.getOutputTypes()).resolves.toEqual({ 'text/html': 1 });
await expect(converter.getOutputTypes('internal/error')).resolves.toEqual({ 'text/html': 1 });
});
it('works with non-HTTP errors.', async(): Promise<void> => {

View File

@@ -8,8 +8,8 @@ describe('A FormToJsonConverter', (): void => {
const converter = new FormToJsonConverter();
it('supports going from form data to json.', async(): Promise<void> => {
await expect(converter.getInputTypes()).resolves.toEqual({ 'application/x-www-form-urlencoded': 1 });
await expect(converter.getOutputTypes()).resolves.toEqual({ 'application/json': 1 });
await expect(converter.getOutputTypes('application/x-www-form-urlencoded'))
.resolves.toEqual({ 'application/json': 1 });
});
it('converts form data to JSON.', async(): Promise<void> => {

View File

@@ -17,8 +17,7 @@ describe('A MarkdownToHtmlConverter', (): void => {
});
it('supports going from markdown to html.', async(): Promise<void> => {
await expect(converter.getInputTypes()).resolves.toEqual({ 'text/markdown': 1 });
await expect(converter.getOutputTypes()).resolves.toEqual({ 'text/html': 1 });
await expect(converter.getOutputTypes('text/markdown')).resolves.toEqual({ 'text/html': 1 });
});
it('converts markdown and inserts it in the template.', async(): Promise<void> => {

View File

@@ -19,19 +19,14 @@ describe('A QuadToRdfConverter', (): void => {
metadata = new RepresentationMetadata(identifier, INTERNAL_QUADS);
});
it('supports parsing quads.', async(): Promise<void> => {
await expect(new QuadToRdfConverter().getInputTypes())
.resolves.toEqual({ [INTERNAL_QUADS]: 1 });
});
it('defaults to rdfSerializer preferences when given no output preferences.', async(): Promise<void> => {
await expect(new QuadToRdfConverter().getOutputTypes())
await expect(new QuadToRdfConverter().getOutputTypes(INTERNAL_QUADS))
.resolves.toEqual(await rdfSerializer.getContentTypesPrioritized());
});
it('supports overriding output preferences.', async(): Promise<void> => {
const outputPreferences = { 'text/turtle': 1 };
await expect(new QuadToRdfConverter({ outputPreferences }).getOutputTypes())
await expect(new QuadToRdfConverter({ outputPreferences }).getOutputTypes(INTERNAL_QUADS))
.resolves.toEqual(outputPreferences);
});

View File

@@ -16,12 +16,11 @@ describe('A RdfToQuadConverter', (): void => {
const converter = new RdfToQuadConverter();
const identifier: ResourceIdentifier = { path: 'path' };
it('supports parsing the same types as rdfParser.', async(): Promise<void> => {
await expect(converter.getInputTypes()).resolves.toEqual(await rdfParser.getContentTypesPrioritized());
});
it('supports serializing as quads.', async(): Promise<void> => {
await expect(converter.getOutputTypes()).resolves.toEqual({ [INTERNAL_QUADS]: 1 });
const types = Object.entries(await rdfParser.getContentTypesPrioritized());
for (const [ type, weight ] of types) {
await expect(converter.getOutputTypes(type)).resolves.toEqual({ [INTERNAL_QUADS]: weight });
}
});
it('can handle turtle to quad conversions.', async(): Promise<void> => {