mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
119 lines
5.2 KiB
TypeScript
119 lines
5.2 KiB
TypeScript
import type { Patch } from '../../../../src/ldp/http/Patch';
|
|
import { BasicRepresentation } from '../../../../src/ldp/representation/BasicRepresentation';
|
|
import type { Representation } from '../../../../src/ldp/representation/Representation';
|
|
import type { ResourceIdentifier } from '../../../../src/ldp/representation/ResourceIdentifier';
|
|
import type {
|
|
RepresentationConverter,
|
|
RepresentationConverterArgs,
|
|
} from '../../../../src/storage/conversion/RepresentationConverter';
|
|
import { ConvertingPatchHandler } from '../../../../src/storage/patch/ConvertingPatchHandler';
|
|
import type { PatchHandlerArgs } from '../../../../src/storage/patch/PatchHandler';
|
|
import type { ResourceStore } from '../../../../src/storage/ResourceStore';
|
|
import { NotFoundHttpError } from '../../../../src/util/errors/NotFoundHttpError';
|
|
|
|
class SimpleConvertingPatchHandler extends ConvertingPatchHandler {
|
|
private readonly type: string;
|
|
|
|
public constructor(converter: RepresentationConverter, intermediateType: string, defaultType: string) {
|
|
super(converter, intermediateType, defaultType);
|
|
this.type = intermediateType;
|
|
}
|
|
|
|
public async patch(input: PatchHandlerArgs, representation?: Representation): Promise<Representation> {
|
|
return representation ?
|
|
new BasicRepresentation('patched', representation.metadata) :
|
|
new BasicRepresentation('patched', input.identifier, this.type);
|
|
}
|
|
}
|
|
|
|
describe('A ConvertingPatchHandler', (): void => {
|
|
const intermediateType = 'internal/quads';
|
|
const defaultType = 'text/turtle';
|
|
const identifier: ResourceIdentifier = { path: 'http://test.com/foo' };
|
|
const patch: Patch = new BasicRepresentation([], 'type/patch');
|
|
const representation: Representation = new BasicRepresentation([], 'application/trig');
|
|
let source: jest.Mocked<ResourceStore>;
|
|
let args: PatchHandlerArgs;
|
|
let converter: jest.Mocked<RepresentationConverter>;
|
|
let handler: jest.Mocked<SimpleConvertingPatchHandler>;
|
|
|
|
beforeEach(async(): Promise<void> => {
|
|
converter = {
|
|
handleSafe: jest.fn(async({ preferences }: RepresentationConverterArgs): Promise<any> =>
|
|
new BasicRepresentation('converted', Object.keys(preferences.type!)[0])),
|
|
} as any;
|
|
|
|
source = {
|
|
getRepresentation: jest.fn().mockResolvedValue(representation),
|
|
setRepresentation: jest.fn(async(id: ResourceIdentifier): Promise<ResourceIdentifier[]> => [ id ]),
|
|
} as any;
|
|
|
|
args = { patch, identifier, source };
|
|
|
|
handler = new SimpleConvertingPatchHandler(converter, intermediateType, defaultType) as any;
|
|
jest.spyOn(handler, 'patch');
|
|
});
|
|
|
|
it('converts the representation before calling the patch function.', async(): Promise<void> => {
|
|
await expect(handler.handle(args)).resolves.toEqual([ identifier ]);
|
|
|
|
// Convert input
|
|
expect(source.getRepresentation).toHaveBeenCalledTimes(1);
|
|
expect(source.getRepresentation).toHaveBeenLastCalledWith(identifier, { });
|
|
expect(converter.handleSafe).toHaveBeenCalledTimes(2);
|
|
expect(converter.handleSafe).toHaveBeenCalledWith({
|
|
representation: await source.getRepresentation.mock.results[0].value,
|
|
identifier,
|
|
preferences: { type: { [intermediateType]: 1 }},
|
|
});
|
|
|
|
// Patch
|
|
expect(handler.patch).toHaveBeenCalledTimes(1);
|
|
expect(handler.patch).toHaveBeenLastCalledWith(args, await converter.handleSafe.mock.results[0].value);
|
|
|
|
// Convert back
|
|
expect(converter.handleSafe).toHaveBeenLastCalledWith({
|
|
representation: await handler.patch.mock.results[0].value,
|
|
identifier,
|
|
preferences: { type: { 'application/trig': 1 }},
|
|
});
|
|
expect(source.setRepresentation).toHaveBeenCalledTimes(1);
|
|
expect(source.setRepresentation)
|
|
.toHaveBeenLastCalledWith(identifier, await converter.handleSafe.mock.results[1].value);
|
|
expect(source.setRepresentation.mock.calls[0][1].metadata.contentType).toBe(representation.metadata.contentType);
|
|
});
|
|
|
|
it('expects the patch function to create a new representation if there is none.', async(): Promise<void> => {
|
|
source.getRepresentation.mockRejectedValueOnce(new NotFoundHttpError());
|
|
|
|
await expect(handler.handle(args)).resolves.toEqual([ identifier ]);
|
|
|
|
// Try to get input
|
|
expect(source.getRepresentation).toHaveBeenCalledTimes(1);
|
|
expect(source.getRepresentation).toHaveBeenLastCalledWith(identifier, { });
|
|
|
|
// Patch
|
|
expect(handler.patch).toHaveBeenCalledTimes(1);
|
|
expect(handler.patch).toHaveBeenLastCalledWith(args, undefined);
|
|
|
|
// Convert new Representation to default type
|
|
expect(converter.handleSafe).toHaveBeenCalledTimes(1);
|
|
expect(converter.handleSafe).toHaveBeenLastCalledWith({
|
|
representation: await handler.patch.mock.results[0].value,
|
|
identifier,
|
|
preferences: { type: { [defaultType]: 1 }},
|
|
});
|
|
expect(source.setRepresentation).toHaveBeenCalledTimes(1);
|
|
expect(source.setRepresentation)
|
|
.toHaveBeenLastCalledWith(identifier, await converter.handleSafe.mock.results[0].value);
|
|
expect(source.setRepresentation.mock.calls[0][1].metadata.contentType).toBe(defaultType);
|
|
});
|
|
|
|
it('rethrows the error if something goes wrong getting the representation.', async(): Promise<void> => {
|
|
const error = new Error('bad data');
|
|
source.getRepresentation.mockRejectedValueOnce(error);
|
|
|
|
await expect(handler.handle(args)).rejects.toThrow(error);
|
|
});
|
|
});
|