From fa94c7d4bb0d67b0cde264f9515260293b3b904a Mon Sep 17 00:00:00 2001 From: Joachim Van Herwegen Date: Tue, 26 Oct 2021 16:30:10 +0200 Subject: [PATCH] feat: Determine Typed Converter output based on input type --- .../BaseTypedRepresentationConverter.ts | 46 ++++++------ src/storage/conversion/ChainedConverter.ts | 72 +++++++++---------- src/storage/conversion/ConversionUtil.ts | 10 +++ .../conversion/ErrorToTemplateConverter.ts | 2 +- src/storage/conversion/QuadToRdfConverter.ts | 4 +- .../TypedRepresentationConverter.ts | 9 +-- test/integration/GuardedStream.test.ts | 10 +-- .../BaseTypedRepresentationConverter.test.ts | 35 +++------ .../conversion/ChainedConverter.test.ts | 10 +-- .../storage/conversion/ConversionUtil.test.ts | 9 ++- .../conversion/ErrorToJsonConverter.test.ts | 3 +- .../conversion/ErrorToQuadConverter.test.ts | 3 +- .../ErrorToTemplateConverter.test.ts | 3 +- .../conversion/FormToJsonConverter.test.ts | 4 +- .../MarkdownToHtmlConverter.test.ts | 3 +- .../conversion/QuadToRdfConverter.test.ts | 9 +-- .../conversion/RdfToQuadConverter.test.ts | 9 ++- 17 files changed, 107 insertions(+), 134 deletions(-) diff --git a/src/storage/conversion/BaseTypedRepresentationConverter.ts b/src/storage/conversion/BaseTypedRepresentationConverter.ts index 3fc2a769f..e5e3c40b6 100644 --- a/src/storage/conversion/BaseTypedRepresentationConverter.ts +++ b/src/storage/conversion/BaseTypedRepresentationConverter.ts @@ -1,8 +1,8 @@ import type { ValuePreferences } from '../../http/representation/RepresentationPreferences'; import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpError'; -import { getConversionTarget, getTypeWeight } from './ConversionUtil'; -import { RepresentationConverter } from './RepresentationConverter'; +import { getConversionTarget, getTypeWeight, preferencesToString } from './ConversionUtil'; import type { RepresentationConverterArgs } from './RepresentationConverter'; +import { TypedRepresentationConverter } from './TypedRepresentationConverter'; type PromiseOrValue = T | Promise; type ValuePreferencesArg = @@ -22,30 +22,37 @@ async function toValuePreferences(arg: ValuePreferencesArg): Promise; protected outputTypes: Promise; - public constructor(inputTypes: ValuePreferencesArg = {}, outputTypes: ValuePreferencesArg = {}) { + public constructor(inputTypes: ValuePreferencesArg, outputTypes: ValuePreferencesArg) { super(); this.inputTypes = toValuePreferences(inputTypes); this.outputTypes = toValuePreferences(outputTypes); } /** - * Gets the supported input content types for this converter, mapped to a numerical priority. + * Matches all inputs to all outputs. */ - public async getInputTypes(): Promise { - return this.inputTypes; - } - - /** - * Gets the supported output content types for this converter, mapped to a numerical quality. - */ - public async getOutputTypes(): Promise { - return this.outputTypes; + public async getOutputTypes(contentType: string): Promise { + const weight = getTypeWeight(contentType, await this.inputTypes); + if (weight > 0) { + const outputTypes = { ...await this.outputTypes }; + for (const [ key, value ] of Object.entries(outputTypes)) { + outputTypes[key] = value * weight; + } + return outputTypes; + } + return {}; } /** @@ -57,19 +64,18 @@ export abstract class BaseTypedRepresentationConverter extends RepresentationCon * Throws an error with details if conversion is not possible. */ public async canHandle(args: RepresentationConverterArgs): Promise { - const types = [ this.getInputTypes(), this.getOutputTypes() ]; const { contentType } = args.representation.metadata; if (!contentType) { throw new NotImplementedHttpError('Can not convert data without a Content-Type.'); } - const [ inputTypes, outputTypes ] = await Promise.all(types); + const outputTypes = await this.getOutputTypes(contentType); const outputPreferences = args.preferences.type ?? {}; - if (getTypeWeight(contentType, inputTypes) === 0 || !getConversionTarget(outputTypes, outputPreferences)) { + if (!getConversionTarget(outputTypes, outputPreferences)) { throw new NotImplementedHttpError( - `Cannot convert from ${contentType} to ${Object.keys(outputPreferences) - }, only from ${Object.keys(inputTypes)} to ${Object.keys(outputTypes)}.`, + `Cannot convert from ${contentType} to ${preferencesToString(outputPreferences) + }, only to ${preferencesToString(outputTypes)}.`, ); } } diff --git a/src/storage/conversion/ChainedConverter.ts b/src/storage/conversion/ChainedConverter.ts index f1c765d24..569727412 100644 --- a/src/storage/conversion/ChainedConverter.ts +++ b/src/storage/conversion/ChainedConverter.ts @@ -3,12 +3,16 @@ import type { ValuePreference, ValuePreferences } from '../../http/representatio import { getLoggerFor } from '../../logging/LogUtil'; import { BadRequestHttpError } from '../../util/errors/BadRequestHttpError'; import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpError'; -import { cleanPreferences, getBestPreference, getTypeWeight } from './ConversionUtil'; +import { cleanPreferences, getBestPreference, getTypeWeight, preferencesToString } from './ConversionUtil'; import type { RepresentationConverterArgs } from './RepresentationConverter'; import { RepresentationConverter } from './RepresentationConverter'; import type { TypedRepresentationConverter } from './TypedRepresentationConverter'; -type ConverterPreference = ValuePreference & { converter: TypedRepresentationConverter }; +type ConverterPreference = { + converter: TypedRepresentationConverter; + inType: string; + outTypes: ValuePreferences; +}; /** * A chain of converters that can go from `inTypes` to `outTypes`. @@ -17,16 +21,15 @@ type ConverterPreference = ValuePreference & { converter: TypedRepresentationCon type ConversionPath = { converters: TypedRepresentationConverter[]; intermediateTypes: string[]; - inTypes: ValuePreferences; + inType: string; outTypes: ValuePreferences; }; /** - * The result of applying a `ConversionPath` to a specific input. + * The result of choosing a specific output for a `ConversionPath`. */ type MatchedPath = { path: ConversionPath; - inType: string; outType: string; weight: number; }; @@ -78,8 +81,8 @@ export class ChainedConverter extends RepresentationConverter { return input.representation; } - const { path, inType, outType } = match; - this.logger.debug(`Converting ${inType} -> ${[ ...path.intermediateTypes, outType ].join(' -> ')}.`); + const { path, outType } = match; + this.logger.debug(`Converting ${path.inType} -> ${[ ...path.intermediateTypes, outType ].join(' -> ')}.`); const args = { ...input }; for (let i = 0; i < path.converters.length - 1; ++i) { @@ -105,7 +108,7 @@ export class ChainedConverter extends RepresentationConverter { const weight = getTypeWeight(type, preferences); if (weight > 0) { - this.logger.debug(`No conversion required: ${type} already matches ${Object.keys(preferences)}`); + this.logger.debug(`No conversion required: ${type} already matches ${preferencesToString(preferences)}`); return { value: type, weight }; } @@ -122,13 +125,13 @@ export class ChainedConverter extends RepresentationConverter { // Generate paths from all converters that match the input type let paths = await this.converters.reduce(async(matches: Promise, converter): Promise => { - const inTypes = await converter.getInputTypes(); - if (getTypeWeight(inType, inTypes) > 0) { + const outTypes = await converter.getOutputTypes(inType); + if (Object.keys(outTypes).length > 0) { (await matches).push({ converters: [ converter ], intermediateTypes: [], - inTypes, - outTypes: await converter.getOutputTypes(), + inType, + outTypes, }); } return matches; @@ -137,18 +140,18 @@ export class ChainedConverter extends RepresentationConverter { // It's impossible for a path to have a higher weight than this value const maxWeight = Math.max(...Object.values(outPreferences)); - let bestPath = this.findBest(inType, outPreferences, paths); - paths = this.removeBadPaths(paths, maxWeight, inType, bestPath); + let bestPath = this.findBest(outPreferences, paths); + paths = this.removeBadPaths(paths, maxWeight, bestPath); // This will always stop at some point since paths can't have the same converter twice while (paths.length > 0) { // For every path, find all the paths that can be made by adding 1 more converter const promises = paths.map(async(path): Promise => this.takeStep(path)); paths = (await Promise.all(promises)).flat(); - const newBest = this.findBest(inType, outPreferences, paths); + const newBest = this.findBest(outPreferences, paths); if (newBest && (!bestPath || newBest.weight > bestPath.weight)) { bestPath = newBest; } - paths = this.removeBadPaths(paths, maxWeight, inType, bestPath); + paths = this.removeBadPaths(paths, maxWeight, bestPath); } if (!bestPath) { @@ -161,18 +164,17 @@ export class ChainedConverter extends RepresentationConverter { } /** - * Finds the path from the given list that can convert the given type to the given preferences. + * Finds the path from the given list that can convert to the given preferences. * If there are multiple matches the one with the highest result weight gets chosen. * Will return undefined if there are no matches. */ - private findBest(type: string, preferences: ValuePreferences, paths: ConversionPath[]): MatchedPath | undefined { + private findBest(preferences: ValuePreferences, paths: ConversionPath[]): MatchedPath | undefined { // Need to use null instead of undefined so `reduce` doesn't take the first element of the array as `best` return paths.reduce((best: MatchedPath | null, path): MatchedPath | null => { const outMatch = getBestPreference(path.outTypes, preferences); if (outMatch && !(best && best.weight >= outMatch.weight)) { // Create new MatchedPath, using the output match above - const inWeight = getTypeWeight(type, path.inTypes); - return { path, inType: type, outType: outMatch.value, weight: inWeight * outMatch.weight }; + return { path, outType: outMatch.value, weight: outMatch.weight }; } return best; }, null) ?? undefined; @@ -184,11 +186,9 @@ export class ChainedConverter extends RepresentationConverter { * * @param paths - Paths to filter. * @param maxWeight - The maximum weight in the output preferences. - * @param inType - The input type. * @param bestMatch - The current best path. */ - private removeBadPaths(paths: ConversionPath[], maxWeight: number, inType: string, bestMatch?: MatchedPath): - ConversionPath[] { + private removeBadPaths(paths: ConversionPath[], maxWeight: number, bestMatch?: MatchedPath): ConversionPath[] { // All paths are still good if there is no best match yet if (!bestMatch) { return paths; @@ -200,9 +200,7 @@ export class ChainedConverter extends RepresentationConverter { // Only return paths that can potentially improve upon bestPath return paths.filter((path): boolean => { - const optimisticWeight = getTypeWeight(inType, path.inTypes) * - Math.max(...Object.values(path.outTypes)) * - maxWeight; + const optimisticWeight = Math.max(...Object.values(path.outTypes)) * maxWeight; return optimisticWeight > bestMatch.weight; }); } @@ -218,9 +216,9 @@ export class ChainedConverter extends RepresentationConverter { // Create a new path for every converter that can be appended return Promise.all(nextConverters.map(async(pref): Promise => ({ converters: [ ...path.converters, pref.converter ], - intermediateTypes: [ ...path.intermediateTypes, pref.value ], - inTypes: path.inTypes, - outTypes: this.modifyTypeWeights(pref.weight, await pref.converter.getOutputTypes()), + intermediateTypes: [ ...path.intermediateTypes, pref.inType ], + inType: path.inType, + outTypes: pref.outTypes, }))); } @@ -237,13 +235,15 @@ export class ChainedConverter extends RepresentationConverter { */ private async supportedConverters(types: ValuePreferences, converters: TypedRepresentationConverter[]): Promise { - const promises = converters.map(async(converter): Promise => { - const inputTypes = await converter.getInputTypes(); - const match = getBestPreference(types, inputTypes); - if (match) { - return { ...match, converter }; + const typeEntries = Object.entries(types); + const results: ConverterPreference[] = []; + for (const converter of converters) { + for (const [ inType, weight ] of typeEntries) { + let outTypes = await converter.getOutputTypes(inType); + outTypes = this.modifyTypeWeights(weight, outTypes); + results.push({ converter, inType, outTypes }); } - }); - return (await Promise.all(promises)).filter(Boolean) as ConverterPreference[]; + } + return results; } } diff --git a/src/storage/conversion/ConversionUtil.ts b/src/storage/conversion/ConversionUtil.ts index 1ed97dc9f..c237061fe 100644 --- a/src/storage/conversion/ConversionUtil.ts +++ b/src/storage/conversion/ConversionUtil.ts @@ -164,3 +164,13 @@ export function matchesMediaType(mediaA: string, mediaB: string): boolean { export function isInternalContentType(contentType?: string): boolean { return typeof contentType !== 'undefined' && matchesMediaType(contentType, INTERNAL_ALL); } + +/** + * Serializes a preferences object to a string for display purposes. + * @param preferences - Preferences to serialize + */ +export function preferencesToString(preferences: ValuePreferences): string { + return Object.entries(preferences) + .map(([ type, weight ]): string => `${type}:${weight}`) + .join(','); +} diff --git a/src/storage/conversion/ErrorToTemplateConverter.ts b/src/storage/conversion/ErrorToTemplateConverter.ts index 923226fa2..563668a54 100644 --- a/src/storage/conversion/ErrorToTemplateConverter.ts +++ b/src/storage/conversion/ErrorToTemplateConverter.ts @@ -43,7 +43,7 @@ export class ErrorToTemplateConverter extends BaseTypedRepresentationConverter { private readonly contentType: string; public constructor(templateEngine: TemplateEngine, templateOptions?: TemplateOptions) { - super(INTERNAL_ERROR, templateOptions?.contentType ?? DEFAULT_TEMPLATE_OPTIONS.contentType); + super(INTERNAL_ERROR, templateOptions?.contentType ?? DEFAULT_TEMPLATE_OPTIONS.contentType!); // Workaround for https://github.com/LinkedSoftwareDependencies/Components.js/issues/20 if (!templateOptions || Object.keys(templateOptions).length === 0) { templateOptions = DEFAULT_TEMPLATE_OPTIONS; diff --git a/src/storage/conversion/QuadToRdfConverter.ts b/src/storage/conversion/QuadToRdfConverter.ts index e343f3b67..6432c6555 100644 --- a/src/storage/conversion/QuadToRdfConverter.ts +++ b/src/storage/conversion/QuadToRdfConverter.ts @@ -27,7 +27,7 @@ export class QuadToRdfConverter extends BaseTypedRepresentationConverter { public async handle({ identifier, representation: quads, preferences }: RepresentationConverterArgs): Promise { // Can not be undefined if the `canHandle` call passed - const contentType = getConversionTarget(await this.getOutputTypes(), preferences.type)!; + const contentType = getConversionTarget(await this.getOutputTypes(INTERNAL_QUADS), preferences.type)!; let data: Readable; // Use prefixes if possible (see https://github.com/rubensworks/rdf-serialize.js/issues/1) @@ -36,7 +36,7 @@ export class QuadToRdfConverter extends BaseTypedRepresentationConverter { .map(({ subject, object }): [string, string] => [ object.value, subject.value ])); const options = { format: contentType, baseIRI: identifier.path, prefixes }; data = pipeSafely(quads.data, new StreamWriter(options)); - // Otherwise, write without prefixes + // Otherwise, write without prefixes } else { data = rdfSerializer.serialize(quads.data, { contentType }) as Readable; } diff --git a/src/storage/conversion/TypedRepresentationConverter.ts b/src/storage/conversion/TypedRepresentationConverter.ts index 60e41b31d..295664c9c 100644 --- a/src/storage/conversion/TypedRepresentationConverter.ts +++ b/src/storage/conversion/TypedRepresentationConverter.ts @@ -6,12 +6,7 @@ import { RepresentationConverter } from './RepresentationConverter'; */ export abstract class TypedRepresentationConverter extends RepresentationConverter { /** - * Gets the supported input content types for this converter, mapped to a numerical priority. + * Gets the output content types this converter can convert the input type to, mapped to a numerical priority. */ - public abstract getInputTypes(): Promise; - - /** - * Gets the supported output content types for this converter, mapped to a numerical quality. - */ - public abstract getOutputTypes(): Promise; + public abstract getOutputTypes(contentType: string): Promise; } diff --git a/test/integration/GuardedStream.test.ts b/test/integration/GuardedStream.test.ts index 1cadb4906..4963da1d5 100644 --- a/test/integration/GuardedStream.test.ts +++ b/test/integration/GuardedStream.test.ts @@ -22,15 +22,7 @@ const logger: jest.Mocked = getLoggerFor('GuardedStream') as any; class DummyConverter extends BaseTypedRepresentationConverter { public constructor() { - super('*/*', 'custom/type'); - } - - public async getInputTypes(): Promise> { - return { [INTERNAL_QUADS]: 1 }; - } - - public async getOutputTypes(): Promise> { - return { 'x/x': 1 }; + super(INTERNAL_QUADS, 'x/x'); } public async handle({ representation }: RepresentationConverterArgs): Promise { diff --git a/test/unit/storage/conversion/BaseTypedRepresentationConverter.test.ts b/test/unit/storage/conversion/BaseTypedRepresentationConverter.test.ts index dc82d1664..3f25a68de 100644 --- a/test/unit/storage/conversion/BaseTypedRepresentationConverter.test.ts +++ b/test/unit/storage/conversion/BaseTypedRepresentationConverter.test.ts @@ -7,56 +7,37 @@ class CustomTypedRepresentationConverter extends BaseTypedRepresentationConverte } describe('A BaseTypedRepresentationConverter', (): void => { - it('defaults to allowing everything.', async(): Promise => { - const converter = new CustomTypedRepresentationConverter(); - await expect(converter.getInputTypes()).resolves.toEqual({ - }); - await expect(converter.getOutputTypes()).resolves.toEqual({ - }); - }); - it('accepts strings.', async(): Promise => { 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 => { 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 => { 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 => { 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 => { 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); }); diff --git a/test/unit/storage/conversion/ChainedConverter.test.ts b/test/unit/storage/conversion/ChainedConverter.test.ts index 8c98cf990..d75c1a212 100644 --- a/test/unit/storage/conversion/ChainedConverter.test.ts +++ b/test/unit/storage/conversion/ChainedConverter.test.ts @@ -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 { - return this.inTypes; - } - - public async getOutputTypes(): Promise { - return this.outTypes; - } - public async handle(input: RepresentationConverterArgs): Promise { // Make sure the input type is supported const inType = input.representation.metadata.contentType!; diff --git a/test/unit/storage/conversion/ConversionUtil.test.ts b/test/unit/storage/conversion/ConversionUtil.test.ts index bba2123f5..42124518e 100644 --- a/test/unit/storage/conversion/ConversionUtil.test.ts +++ b/test/unit/storage/conversion/ConversionUtil.test.ts @@ -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 => { + 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'); + }); + }); }); diff --git a/test/unit/storage/conversion/ErrorToJsonConverter.test.ts b/test/unit/storage/conversion/ErrorToJsonConverter.test.ts index a7c0fc4f8..1b9ca1f01 100644 --- a/test/unit/storage/conversion/ErrorToJsonConverter.test.ts +++ b/test/unit/storage/conversion/ErrorToJsonConverter.test.ts @@ -9,8 +9,7 @@ describe('An ErrorToJsonConverter', (): void => { const preferences = {}; it('supports going from errors to json.', async(): Promise => { - 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 => { diff --git a/test/unit/storage/conversion/ErrorToQuadConverter.test.ts b/test/unit/storage/conversion/ErrorToQuadConverter.test.ts index 3def938e0..68736d7e8 100644 --- a/test/unit/storage/conversion/ErrorToQuadConverter.test.ts +++ b/test/unit/storage/conversion/ErrorToQuadConverter.test.ts @@ -13,8 +13,7 @@ describe('An ErrorToQuadConverter', (): void => { const preferences = {}; it('supports going from errors to quads.', async(): Promise => { - 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 => { diff --git a/test/unit/storage/conversion/ErrorToTemplateConverter.test.ts b/test/unit/storage/conversion/ErrorToTemplateConverter.test.ts index ecc3fe861..27f106859 100644 --- a/test/unit/storage/conversion/ErrorToTemplateConverter.test.ts +++ b/test/unit/storage/conversion/ErrorToTemplateConverter.test.ts @@ -24,8 +24,7 @@ describe('An ErrorToTemplateConverter', (): void => { }); it('supports going from errors to the given content type.', async(): Promise => { - 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 => { diff --git a/test/unit/storage/conversion/FormToJsonConverter.test.ts b/test/unit/storage/conversion/FormToJsonConverter.test.ts index 11fbb5e4b..4f7d89d35 100644 --- a/test/unit/storage/conversion/FormToJsonConverter.test.ts +++ b/test/unit/storage/conversion/FormToJsonConverter.test.ts @@ -8,8 +8,8 @@ describe('A FormToJsonConverter', (): void => { const converter = new FormToJsonConverter(); it('supports going from form data to json.', async(): Promise => { - 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 => { diff --git a/test/unit/storage/conversion/MarkdownToHtmlConverter.test.ts b/test/unit/storage/conversion/MarkdownToHtmlConverter.test.ts index 733142b1f..7c3cb7c7c 100644 --- a/test/unit/storage/conversion/MarkdownToHtmlConverter.test.ts +++ b/test/unit/storage/conversion/MarkdownToHtmlConverter.test.ts @@ -17,8 +17,7 @@ describe('A MarkdownToHtmlConverter', (): void => { }); it('supports going from markdown to html.', async(): Promise => { - 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 => { diff --git a/test/unit/storage/conversion/QuadToRdfConverter.test.ts b/test/unit/storage/conversion/QuadToRdfConverter.test.ts index 6b83c0ccb..983b4a2be 100644 --- a/test/unit/storage/conversion/QuadToRdfConverter.test.ts +++ b/test/unit/storage/conversion/QuadToRdfConverter.test.ts @@ -19,19 +19,14 @@ describe('A QuadToRdfConverter', (): void => { metadata = new RepresentationMetadata(identifier, INTERNAL_QUADS); }); - it('supports parsing quads.', async(): Promise => { - await expect(new QuadToRdfConverter().getInputTypes()) - .resolves.toEqual({ [INTERNAL_QUADS]: 1 }); - }); - it('defaults to rdfSerializer preferences when given no output preferences.', async(): Promise => { - await expect(new QuadToRdfConverter().getOutputTypes()) + await expect(new QuadToRdfConverter().getOutputTypes(INTERNAL_QUADS)) .resolves.toEqual(await rdfSerializer.getContentTypesPrioritized()); }); it('supports overriding output preferences.', async(): Promise => { const outputPreferences = { 'text/turtle': 1 }; - await expect(new QuadToRdfConverter({ outputPreferences }).getOutputTypes()) + await expect(new QuadToRdfConverter({ outputPreferences }).getOutputTypes(INTERNAL_QUADS)) .resolves.toEqual(outputPreferences); }); diff --git a/test/unit/storage/conversion/RdfToQuadConverter.test.ts b/test/unit/storage/conversion/RdfToQuadConverter.test.ts index a197eba98..6a04cc867 100644 --- a/test/unit/storage/conversion/RdfToQuadConverter.test.ts +++ b/test/unit/storage/conversion/RdfToQuadConverter.test.ts @@ -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 => { - await expect(converter.getInputTypes()).resolves.toEqual(await rdfParser.getContentTypesPrioritized()); - }); - it('supports serializing as quads.', async(): Promise => { - 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 => {