import { BasicRepresentation } from '../../../../src/http/representation/BasicRepresentation'; import type { Representation } from '../../../../src/http/representation/Representation'; import { RepresentationMetadata } from '../../../../src/http/representation/RepresentationMetadata'; import type { ResourceIdentifier } from '../../../../src/http/representation/ResourceIdentifier'; import { JsonResourceStorage } from '../../../../src/storage/keyvalue/JsonResourceStorage'; import type { ResourceStore } from '../../../../src/storage/ResourceStore'; import { NotFoundHttpError } from '../../../../src/util/errors/NotFoundHttpError'; import { NotImplementedHttpError } from '../../../../src/util/errors/NotImplementedHttpError'; import { readableToString } from '../../../../src/util/StreamUtil'; import { LDP } from '../../../../src/util/Vocabularies'; describe('A JsonResourceStorage', (): void => { const baseUrl = 'http://test.com/'; const container = '/data/'; const identifier1 = 'http://test.com/foo'; const identifier2 = 'http://test.com/bar'; let store: ResourceStore; let storage: JsonResourceStorage; beforeEach(async(): Promise => { const data: Record = { }; store = { async hasResource(identifier: ResourceIdentifier): Promise { return Boolean(data[identifier.path]); }, async getRepresentation(identifier: ResourceIdentifier): Promise { // Simulate container metadata if (identifier.path === 'http://test.com/data/' && Object.keys(data).length > 0) { const metadata = new RepresentationMetadata({ [LDP.contains]: Object.keys(data) }); return new BasicRepresentation('', metadata); } if (!data[identifier.path]) { throw new NotFoundHttpError(); } return new BasicRepresentation(data[identifier.path], identifier); }, async setRepresentation(identifier: ResourceIdentifier, representation: Representation): Promise { data[identifier.path] = await readableToString(representation.data); }, async deleteResource(identifier: ResourceIdentifier): Promise { if (!data[identifier.path]) { throw new NotFoundHttpError(); } // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete data[identifier.path]; }, } as any; storage = new JsonResourceStorage(store, baseUrl, container); }); it('returns undefined if there is no matching data.', async(): Promise => { await expect(storage.get(identifier1)).resolves.toBeUndefined(); }); it('errors when trying to request entries.', async(): Promise => { expect((): never => storage.entries()).toThrow(NotImplementedHttpError); }); it('returns data if it was set beforehand.', async(): Promise => { await expect(storage.set(identifier1, 'apple')).resolves.toBe(storage); await expect(storage.get(identifier1)).resolves.toBe('apple'); }); it('can check if data is present.', async(): Promise => { await expect(storage.has(identifier1)).resolves.toBe(false); await expect(storage.set(identifier1, 'apple')).resolves.toBe(storage); await expect(storage.has(identifier1)).resolves.toBe(true); }); it('can delete data.', async(): Promise => { await expect(storage.has(identifier1)).resolves.toBe(false); await expect(storage.delete(identifier1)).resolves.toBe(false); await expect(storage.has(identifier1)).resolves.toBe(false); await expect(storage.set(identifier1, 'apple')).resolves.toBe(storage); await expect(storage.has(identifier1)).resolves.toBe(true); await expect(storage.delete(identifier1)).resolves.toBe(true); await expect(storage.has(identifier1)).resolves.toBe(false); }); it('can handle multiple identifiers.', async(): Promise => { await expect(storage.set(identifier1, 'apple')).resolves.toBe(storage); await expect(storage.has(identifier1)).resolves.toBe(true); await expect(storage.has(identifier2)).resolves.toBe(false); await expect(storage.set(identifier2, 'pear')).resolves.toBe(storage); await expect(storage.get(identifier1)).resolves.toBe('apple'); }); it('re-throws errors thrown by the store.', async(): Promise => { store.getRepresentation = jest.fn().mockRejectedValue(new Error('bad GET')); await expect(storage.get(identifier1)).rejects.toThrow('bad GET'); store.deleteResource = jest.fn().mockRejectedValueOnce(new Error('bad DELETE')); await expect(storage.delete(identifier1)).rejects.toThrow('bad DELETE'); }); });