From 4404fa07d9238aed2afdce29e3a3d1eafed6af0b Mon Sep 17 00:00:00 2001 From: Joachim Van Herwegen Date: Wed, 23 Feb 2022 15:41:31 +0100 Subject: [PATCH] refactor: Rename resourceExists to hasResource The function was also moved to the smaller interface ResourceSet. --- RELEASE_NOTES.md | 2 ++ src/http/ldp/PatchOperationHandler.ts | 2 +- src/http/ldp/PutOperationHandler.ts | 2 +- src/index.ts | 1 + src/pods/GeneratedPodManager.ts | 2 +- src/storage/BaseResourceStore.ts | 2 +- src/storage/DataAccessorBasedStore.ts | 4 ++-- src/storage/LockingResourceStore.ts | 4 ++-- src/storage/MonitoringStore.ts | 4 ++-- src/storage/PassthroughStore.ts | 4 ++-- src/storage/ResourceSet.ts | 14 ++++++++++++++ src/storage/ResourceStore.ts | 12 ++---------- src/storage/RoutingResourceStore.ts | 4 ++-- src/storage/keyvalue/JsonResourceStorage.ts | 2 +- src/storage/routing/ConvertingRouterRule.ts | 2 +- test/unit/http/ldp/PatchOperationHandler.test.ts | 4 ++-- test/unit/http/ldp/PutOperationHandler.test.ts | 4 ++-- test/unit/pods/GeneratedPodManager.test.ts | 6 +++--- test/unit/storage/BaseResourceStore.test.ts | 4 ++-- test/unit/storage/DataAccessorBasedStore.test.ts | 6 +++--- test/unit/storage/LockingResourceStore.test.ts | 12 ++++++------ test/unit/storage/MonitoringStore.test.ts | 10 +++++----- test/unit/storage/PassthroughStore.test.ts | 10 +++++----- test/unit/storage/RoutingResourceStore.test.ts | 10 +++++----- .../storage/keyvalue/JsonResourceStorage.test.ts | 2 +- .../storage/routing/ConvertingRouterRule.test.ts | 8 ++++---- 26 files changed, 73 insertions(+), 64 deletions(-) create mode 100644 src/storage/ResourceSet.ts diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 66749ddee2..28173cf82d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -21,6 +21,8 @@ The following changes are relevant for v3 custom configs that replaced certain f These changes are relevant if you wrote custom modules for the server that depend on existing interfaces. - The output of `parseContentType` in `HeaderUtil` was changed to include parameters. - `PermissionReader`s take an additional `modes` parameter as input. +- The `ResourceStore` function `resourceExists` has been renamed to `hasResource` + and has been moved to a separate `ResourceSet` interface. ## v3.0.0 ### New features diff --git a/src/http/ldp/PatchOperationHandler.ts b/src/http/ldp/PatchOperationHandler.ts index e17a3da6df..04d0844e05 100644 --- a/src/http/ldp/PatchOperationHandler.ts +++ b/src/http/ldp/PatchOperationHandler.ts @@ -42,7 +42,7 @@ export class PatchOperationHandler extends OperationHandler { // RFC7231, ยง4.3.4: If the target resource does not have a current representation and the // PUT successfully creates one, then the origin server MUST inform the // user agent by sending a 201 (Created) response. - const exists = await this.store.resourceExists(operation.target, operation.conditions); + const exists = await this.store.hasResource(operation.target); await this.store.modifyResource(operation.target, operation.body as Patch, operation.conditions); if (exists) { return new ResetResponseDescription(); diff --git a/src/http/ldp/PutOperationHandler.ts b/src/http/ldp/PutOperationHandler.ts index deb25c2218..eacee16f86 100644 --- a/src/http/ldp/PutOperationHandler.ts +++ b/src/http/ldp/PutOperationHandler.ts @@ -38,7 +38,7 @@ export class PutOperationHandler extends OperationHandler { } // A more efficient approach would be to have the server return metadata indicating if a resource was new // See https://github.com/solid/community-server/issues/632 - const exists = await this.store.resourceExists(operation.target, operation.conditions); + const exists = await this.store.hasResource(operation.target); await this.store.setRepresentation(operation.target, operation.body, operation.conditions); if (exists) { return new ResetResponseDescription(); diff --git a/src/index.ts b/src/index.ts index 8a8830fdc3..51bc27da28 100644 --- a/src/index.ts +++ b/src/index.ts @@ -358,6 +358,7 @@ export * from './storage/PassthroughStore'; export * from './storage/PatchingStore'; export * from './storage/ReadOnlyStore'; export * from './storage/RepresentationConvertingStore'; +export * from './storage/ResourceSet'; export * from './storage/ResourceStore'; export * from './storage/RoutingResourceStore'; diff --git a/src/pods/GeneratedPodManager.ts b/src/pods/GeneratedPodManager.ts index 076ab75d0b..2b3971de66 100644 --- a/src/pods/GeneratedPodManager.ts +++ b/src/pods/GeneratedPodManager.ts @@ -28,7 +28,7 @@ export class GeneratedPodManager implements PodManager { */ public async createPod(identifier: ResourceIdentifier, settings: PodSettings, overwrite: boolean): Promise { this.logger.info(`Creating pod ${identifier.path}`); - if (!overwrite && await this.store.resourceExists(identifier)) { + if (!overwrite && await this.store.hasResource(identifier)) { throw new ConflictHttpError(`There already is a resource at ${identifier.path}`); } diff --git a/src/storage/BaseResourceStore.ts b/src/storage/BaseResourceStore.ts index a6fea66630..16c208e8e9 100644 --- a/src/storage/BaseResourceStore.ts +++ b/src/storage/BaseResourceStore.ts @@ -11,7 +11,7 @@ import type { ResourceStore } from './ResourceStore'; */ /* eslint-disable @typescript-eslint/no-unused-vars */ export class BaseResourceStore implements ResourceStore { - public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions): Promise { + public async hasResource(identifier: ResourceIdentifier): Promise { throw new NotImplementedHttpError(); } diff --git a/src/storage/DataAccessorBasedStore.ts b/src/storage/DataAccessorBasedStore.ts index 570e9c6744..451fde55f4 100644 --- a/src/storage/DataAccessorBasedStore.ts +++ b/src/storage/DataAccessorBasedStore.ts @@ -81,7 +81,7 @@ export class DataAccessorBasedStore implements ResourceStore { this.auxiliaryStrategy = auxiliaryStrategy; } - public async resourceExists(identifier: ResourceIdentifier): Promise { + public async hasResource(identifier: ResourceIdentifier): Promise { try { this.validateIdentifier(identifier); await this.accessor.getMetadata(identifier); @@ -530,7 +530,7 @@ export class DataAccessorBasedStore implements ResourceStore { // Make sure we don't already have a resource with this exact name (or with differing trailing slash) const withSlash = { path: ensureTrailingSlash(newID.path) }; const withoutSlash = { path: trimTrailingSlashes(newID.path) }; - if (await this.resourceExists(withSlash) || await this.resourceExists(withoutSlash)) { + if (await this.hasResource(withSlash) || await this.hasResource(withoutSlash)) { newID = this.createURI(container, isContainer); } diff --git a/src/storage/LockingResourceStore.ts b/src/storage/LockingResourceStore.ts index a8740534ca..ae004ea413 100644 --- a/src/storage/LockingResourceStore.ts +++ b/src/storage/LockingResourceStore.ts @@ -34,9 +34,9 @@ export class LockingResourceStore implements AtomicResourceStore { this.auxiliaryStrategy = auxiliaryStrategy; } - public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions): Promise { + public async hasResource(identifier: ResourceIdentifier): Promise { return this.locks.withReadLock(this.getLockIdentifier(identifier), - async(): Promise => this.source.resourceExists(identifier, conditions)); + async(): Promise => this.source.hasResource(identifier)); } public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences, diff --git a/src/storage/MonitoringStore.ts b/src/storage/MonitoringStore.ts index 307cc2d6d4..d027c5ed81 100644 --- a/src/storage/MonitoringStore.ts +++ b/src/storage/MonitoringStore.ts @@ -19,8 +19,8 @@ export class MonitoringStore this.source = source; } - public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions): Promise { - return this.source.resourceExists(identifier, conditions); + public async hasResource(identifier: ResourceIdentifier): Promise { + return this.source.hasResource(identifier); } public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences, diff --git a/src/storage/PassthroughStore.ts b/src/storage/PassthroughStore.ts index 60254b1ad7..6ab9a5fc23 100644 --- a/src/storage/PassthroughStore.ts +++ b/src/storage/PassthroughStore.ts @@ -17,8 +17,8 @@ export class PassthroughStore implement this.source = source; } - public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions): Promise { - return this.source.resourceExists(identifier, conditions); + public async hasResource(identifier: ResourceIdentifier): Promise { + return this.source.hasResource(identifier); } public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences, diff --git a/src/storage/ResourceSet.ts b/src/storage/ResourceSet.ts new file mode 100644 index 0000000000..05b8fec73d --- /dev/null +++ b/src/storage/ResourceSet.ts @@ -0,0 +1,14 @@ +import type { ResourceIdentifier } from '../http/representation/ResourceIdentifier'; + +/** + * A set containing resources. + */ +export interface ResourceSet { + /** + * Check if a resource exists in this ResourceSet. + * @param identifier - Identifier of resource to check. + * + * @returns A promise resolving if the resource already exists. + */ + hasResource: (identifier: ResourceIdentifier) => Promise; +} diff --git a/src/storage/ResourceStore.ts b/src/storage/ResourceStore.ts index 581cfd2039..57bec1f30f 100644 --- a/src/storage/ResourceStore.ts +++ b/src/storage/ResourceStore.ts @@ -3,6 +3,7 @@ import type { Representation } from '../http/representation/Representation'; import type { RepresentationPreferences } from '../http/representation/RepresentationPreferences'; import type { ResourceIdentifier } from '../http/representation/ResourceIdentifier'; import type { Conditions } from './Conditions'; +import type { ResourceSet } from './ResourceSet'; /** * A ResourceStore represents a collection of resources. @@ -15,16 +16,7 @@ import type { Conditions } from './Conditions'; * ResourceStores are also responsible for taking auxiliary resources into account * should those be relevant to the store. */ -export interface ResourceStore { - - /** - * Check if a resource exists. - * @param identifier - Identifier of resource to check. - * - * @returns A promise resolving if the resource already exists - */ - resourceExists: (identifier: ResourceIdentifier, conditions?: Conditions) => Promise; - +export interface ResourceStore extends ResourceSet { /** * Retrieves a representation of a resource. * @param identifier - Identifier of the resource to read. diff --git a/src/storage/RoutingResourceStore.ts b/src/storage/RoutingResourceStore.ts index c09899c6a5..0cba64bee0 100644 --- a/src/storage/RoutingResourceStore.ts +++ b/src/storage/RoutingResourceStore.ts @@ -20,9 +20,9 @@ export class RoutingResourceStore implements ResourceStore { this.rule = rule; } - public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions): + public async hasResource(identifier: ResourceIdentifier): Promise { - return (await this.getStore(identifier)).resourceExists(identifier, conditions); + return (await this.getStore(identifier)).hasResource(identifier); } public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences, diff --git a/src/storage/keyvalue/JsonResourceStorage.ts b/src/storage/keyvalue/JsonResourceStorage.ts index 794df82e4c..8e7ea7bf18 100644 --- a/src/storage/keyvalue/JsonResourceStorage.ts +++ b/src/storage/keyvalue/JsonResourceStorage.ts @@ -42,7 +42,7 @@ export class JsonResourceStorage implements KeyValueStorage { public async has(key: string): Promise { const identifier = this.createIdentifier(key); - return await this.source.resourceExists(identifier); + return await this.source.hasResource(identifier); } public async set(key: string, value: unknown): Promise { diff --git a/src/storage/routing/ConvertingRouterRule.ts b/src/storage/routing/ConvertingRouterRule.ts index d9b37a752d..404896ccda 100644 --- a/src/storage/routing/ConvertingRouterRule.ts +++ b/src/storage/routing/ConvertingRouterRule.ts @@ -39,7 +39,7 @@ export class ConvertingRouterRule extends RouterRule { entry.supportChecker.supports({ identifier, representation })); } else { // No content-type given so we can only check if one of the stores has data for the identifier - store = await this.findStore(async(entry): Promise => entry.store.resourceExists(identifier)); + store = await this.findStore(async(entry): Promise => entry.store.hasResource(identifier)); } return store; } diff --git a/test/unit/http/ldp/PatchOperationHandler.test.ts b/test/unit/http/ldp/PatchOperationHandler.test.ts index 4bbd6b6108..fda18dcacc 100644 --- a/test/unit/http/ldp/PatchOperationHandler.test.ts +++ b/test/unit/http/ldp/PatchOperationHandler.test.ts @@ -19,7 +19,7 @@ describe('A PatchOperationHandler', (): void => { operation = { method: 'PATCH', target: { path: 'http://test.com/foo' }, body, conditions, preferences: {}}; store = { - resourceExists: jest.fn(), + hasResource: jest.fn(), modifyResource: jest.fn(), } as any; @@ -47,7 +47,7 @@ describe('A PatchOperationHandler', (): void => { }); it('returns the correct response if the resource already exists.', async(): Promise => { - store.resourceExists.mockResolvedValueOnce(true); + store.hasResource.mockResolvedValueOnce(true); const result = await handler.handle({ operation }); expect(store.modifyResource).toHaveBeenCalledTimes(1); expect(store.modifyResource).toHaveBeenLastCalledWith(operation.target, body, conditions); diff --git a/test/unit/http/ldp/PutOperationHandler.test.ts b/test/unit/http/ldp/PutOperationHandler.test.ts index 09f70a0851..a4b00c9174 100644 --- a/test/unit/http/ldp/PutOperationHandler.test.ts +++ b/test/unit/http/ldp/PutOperationHandler.test.ts @@ -18,7 +18,7 @@ describe('A PutOperationHandler', (): void => { body = new BasicRepresentation('', 'text/turtle'); operation = { method: 'PUT', target: { path: 'http://test.com/foo' }, body, conditions, preferences: {}}; store = { - resourceExists: jest.fn(), + hasResource: jest.fn(), setRepresentation: jest.fn(), } as any; @@ -46,7 +46,7 @@ describe('A PutOperationHandler', (): void => { }); it('returns the correct response if the resource already exists.', async(): Promise => { - store.resourceExists.mockResolvedValueOnce(true); + store.hasResource.mockResolvedValueOnce(true); const result = await handler.handle({ operation }); expect(store.setRepresentation).toHaveBeenCalledTimes(1); expect(store.setRepresentation).toHaveBeenLastCalledWith(operation.target, body, conditions); diff --git a/test/unit/pods/GeneratedPodManager.test.ts b/test/unit/pods/GeneratedPodManager.test.ts index 6d1f53b812..1bd241ecbd 100644 --- a/test/unit/pods/GeneratedPodManager.test.ts +++ b/test/unit/pods/GeneratedPodManager.test.ts @@ -20,7 +20,7 @@ describe('A GeneratedPodManager', (): void => { }; store = { setRepresentation: jest.fn(), - resourceExists: jest.fn(), + hasResource: jest.fn(), } as any; generatorData = [ { identifier: { path: '/path/' }, representation: '/' as any }, @@ -36,7 +36,7 @@ describe('A GeneratedPodManager', (): void => { }); it('throws an error if the generate identifier is not available.', async(): Promise => { - store.resourceExists.mockResolvedValueOnce(true); + store.hasResource.mockResolvedValueOnce(true); const result = manager.createPod({ path: `${base}user/` }, settings, false); await expect(result).rejects.toThrow(`There already is a resource at ${base}user/`); await expect(result).rejects.toThrow(ConflictHttpError); @@ -52,7 +52,7 @@ describe('A GeneratedPodManager', (): void => { }); it('allows overwriting when enabled.', async(): Promise => { - store.resourceExists.mockResolvedValueOnce(true); + store.hasResource.mockResolvedValueOnce(true); await expect(manager.createPod({ path: `${base}${settings.login}/` }, settings, true)).resolves.toBeUndefined(); expect(store.setRepresentation).toHaveBeenCalledTimes(3); diff --git a/test/unit/storage/BaseResourceStore.test.ts b/test/unit/storage/BaseResourceStore.test.ts index 30a6746c49..ba9b3fc813 100644 --- a/test/unit/storage/BaseResourceStore.test.ts +++ b/test/unit/storage/BaseResourceStore.test.ts @@ -25,7 +25,7 @@ describe('A BaseResourceStore', (): void => { await expect(store.modifyResource(any, any)).rejects.toThrow(NotImplementedHttpError); }); - it('errors on resourceExists.', async(): Promise => { - await expect(store.resourceExists(any)).rejects.toThrow(NotImplementedHttpError); + it('errors on hasResource.', async(): Promise => { + await expect(store.hasResource(any)).rejects.toThrow(NotImplementedHttpError); }); }); diff --git a/test/unit/storage/DataAccessorBasedStore.test.ts b/test/unit/storage/DataAccessorBasedStore.test.ts index 69f7abda9b..e610330476 100644 --- a/test/unit/storage/DataAccessorBasedStore.test.ts +++ b/test/unit/storage/DataAccessorBasedStore.test.ts @@ -726,13 +726,13 @@ describe('A DataAccessorBasedStore', (): void => { describe('resource Exists', (): void => { it('should return false when the resource does not exist.', async(): Promise => { const resourceID = { path: `${root}resource` }; - await expect(store.resourceExists(resourceID)).resolves.toBeFalsy(); + await expect(store.hasResource(resourceID)).resolves.toBeFalsy(); }); it('should return true when the resource exists.', async(): Promise => { const resourceID = { path: `${root}resource` }; accessor.data[resourceID.path] = representation; - await expect(store.resourceExists(resourceID)).resolves.toBeTruthy(); + await expect(store.hasResource(resourceID)).resolves.toBeTruthy(); }); it('should rethrow any unexpected errors from validateIdentifier.', async(): Promise => { @@ -741,7 +741,7 @@ describe('A DataAccessorBasedStore', (): void => { accessor.getMetadata = jest.fn(async(): Promise => { throw new Error('error'); }); - await expect(store.resourceExists(resourceID)).rejects.toThrow('error'); + await expect(store.hasResource(resourceID)).rejects.toThrow('error'); accessor.getMetadata = originalMetaData; }); }); diff --git a/test/unit/storage/LockingResourceStore.test.ts b/test/unit/storage/LockingResourceStore.test.ts index 5182e09c21..eab0329629 100644 --- a/test/unit/storage/LockingResourceStore.test.ts +++ b/test/unit/storage/LockingResourceStore.test.ts @@ -39,7 +39,7 @@ describe('A LockingResourceStore', (): void => { setRepresentation: jest.fn((): any => addOrder('setRepresentation')), deleteResource: jest.fn((): any => addOrder('deleteResource')), modifyResource: jest.fn((): any => addOrder('modifyResource')), - resourceExists: jest.fn((): any => addOrder('resourceExists')), + hasResource: jest.fn((): any => addOrder('hasResource')), }; timeoutTrigger = new EventEmitter(); @@ -287,12 +287,12 @@ describe('A LockingResourceStore', (): void => { expect(order).toEqual([ 'lock read', 'useless get', 'timeout', 'unlock read' ]); }); - it('resourceExists should only acquire and release the read lock.', async(): Promise => { - await store.resourceExists(subjectId); + it('hasResource should only acquire and release the read lock.', async(): Promise => { + await store.hasResource(subjectId); expect(locker.withReadLock).toHaveBeenCalledTimes(1); expect(locker.withWriteLock).toHaveBeenCalledTimes(0); - expect(source.resourceExists).toHaveBeenCalledTimes(1); - expect(source.resourceExists).toHaveBeenLastCalledWith(subjectId, undefined); - expect(order).toEqual([ 'lock read', 'resourceExists', 'unlock read' ]); + expect(source.hasResource).toHaveBeenCalledTimes(1); + expect(source.hasResource).toHaveBeenLastCalledWith(subjectId); + expect(order).toEqual([ 'lock read', 'hasResource', 'unlock read' ]); }); }); diff --git a/test/unit/storage/MonitoringStore.test.ts b/test/unit/storage/MonitoringStore.test.ts index 2d22f1a728..d8f32bad70 100644 --- a/test/unit/storage/MonitoringStore.test.ts +++ b/test/unit/storage/MonitoringStore.test.ts @@ -19,7 +19,7 @@ describe('A MonitoringStore', (): void => { setRepresentation: jest.fn(async(): Promise => modified), deleteResource: jest.fn(async(): Promise => modified), modifyResource: jest.fn(async(): Promise => modified), - resourceExists: jest.fn(async(): Promise => undefined), + hasResource: jest.fn(async(): Promise => undefined), }; store = new MonitoringStore(source); changedCallback = jest.fn(); @@ -106,9 +106,9 @@ describe('A MonitoringStore', (): void => { expect(changedCallback).toHaveBeenCalledWith({ path: 'http://example.org/modified/2' }); }); - it('calls resourceExists directly from the source.', async(): Promise => { - await expect(store.resourceExists({ path: 'http://example.org/foo/bar' })).resolves.toBeUndefined(); - expect(source.resourceExists).toHaveBeenCalledTimes(1); - expect(source.resourceExists).toHaveBeenLastCalledWith({ path: 'http://example.org/foo/bar' }, undefined); + it('calls hasResource directly from the source.', async(): Promise => { + await expect(store.hasResource({ path: 'http://example.org/foo/bar' })).resolves.toBeUndefined(); + expect(source.hasResource).toHaveBeenCalledTimes(1); + expect(source.hasResource).toHaveBeenLastCalledWith({ path: 'http://example.org/foo/bar' }); }); }); diff --git a/test/unit/storage/PassthroughStore.test.ts b/test/unit/storage/PassthroughStore.test.ts index 4b12ad6b48..715911a94c 100644 --- a/test/unit/storage/PassthroughStore.test.ts +++ b/test/unit/storage/PassthroughStore.test.ts @@ -14,7 +14,7 @@ describe('A PassthroughStore', (): void => { setRepresentation: jest.fn(async(): Promise => 'set'), deleteResource: jest.fn(async(): Promise => 'delete'), modifyResource: jest.fn(async(): Promise => 'modify'), - resourceExists: jest.fn(async(): Promise => 'exists'), + hasResource: jest.fn(async(): Promise => 'exists'), }; store = new PassthroughStore(source); @@ -50,9 +50,9 @@ describe('A PassthroughStore', (): void => { expect(source.modifyResource).toHaveBeenLastCalledWith({ path: 'modifyPath' }, {}, undefined); }); - it('calls resourceExists directly from the source.', async(): Promise => { - await expect(store.resourceExists({ path: 'existsPath' })).resolves.toBe('exists'); - expect(source.resourceExists).toHaveBeenCalledTimes(1); - expect(source.resourceExists).toHaveBeenLastCalledWith({ path: 'existsPath' }, undefined); + it('calls hasResource directly from the source.', async(): Promise => { + await expect(store.hasResource({ path: 'existsPath' })).resolves.toBe('exists'); + expect(source.hasResource).toHaveBeenCalledTimes(1); + expect(source.hasResource).toHaveBeenLastCalledWith({ path: 'existsPath' }); }); }); diff --git a/test/unit/storage/RoutingResourceStore.test.ts b/test/unit/storage/RoutingResourceStore.test.ts index d93256c328..96185ea76d 100644 --- a/test/unit/storage/RoutingResourceStore.test.ts +++ b/test/unit/storage/RoutingResourceStore.test.ts @@ -17,7 +17,7 @@ describe('A RoutingResourceStore', (): void => { setRepresentation: jest.fn(), modifyResource: jest.fn(), deleteResource: jest.fn(), - resourceExists: jest.fn(), + hasResource: jest.fn(), }; rule = new StaticAsyncHandler(true, source); @@ -60,10 +60,10 @@ describe('A RoutingResourceStore', (): void => { expect(source.deleteResource).toHaveBeenLastCalledWith(identifier, 'conditions'); }); - it('calls resourceExists on the resulting store.', async(): Promise => { - await expect(store.resourceExists(identifier)).resolves.toBeUndefined(); - expect(source.resourceExists).toHaveBeenCalledTimes(1); - expect(source.resourceExists).toHaveBeenLastCalledWith(identifier, undefined); + it('calls hasResource on the resulting store.', async(): Promise => { + await expect(store.hasResource(identifier)).resolves.toBeUndefined(); + expect(source.hasResource).toHaveBeenCalledTimes(1); + expect(source.hasResource).toHaveBeenLastCalledWith(identifier); }); it('throws a 404 if there is no body and no store was found.', async(): Promise => { diff --git a/test/unit/storage/keyvalue/JsonResourceStorage.test.ts b/test/unit/storage/keyvalue/JsonResourceStorage.test.ts index ffc0a6ad41..6fd7cede74 100644 --- a/test/unit/storage/keyvalue/JsonResourceStorage.test.ts +++ b/test/unit/storage/keyvalue/JsonResourceStorage.test.ts @@ -19,7 +19,7 @@ describe('A JsonResourceStorage', (): void => { beforeEach(async(): Promise => { const data: Record = { }; store = { - async resourceExists(identifier: ResourceIdentifier): Promise { + async hasResource(identifier: ResourceIdentifier): Promise { return Boolean(data[identifier.path]); }, async getRepresentation(identifier: ResourceIdentifier): Promise { diff --git a/test/unit/storage/routing/ConvertingRouterRule.test.ts b/test/unit/storage/routing/ConvertingRouterRule.test.ts index 94a49ba798..8833eee6ba 100644 --- a/test/unit/storage/routing/ConvertingRouterRule.test.ts +++ b/test/unit/storage/routing/ConvertingRouterRule.test.ts @@ -39,18 +39,18 @@ describe('A ConvertingRouterRule', (): void => { }); it('checks if the stores contain the identifier if there is no data.', async(): Promise => { - store1.resourceExists = jest.fn().mockImplementationOnce((): any => true); + store1.hasResource = jest.fn().mockImplementationOnce((): any => true); await expect(rule.handle({ identifier: { path: 'identifier' }})).resolves.toBe(store1); - expect(store1.resourceExists).toHaveBeenCalledTimes(1); + expect(store1.hasResource).toHaveBeenCalledTimes(1); }); it('returns the defaultStore if no other store has the resource.', async(): Promise => { - store1.resourceExists = jest.fn().mockImplementationOnce((): any => false); + store1.hasResource = jest.fn().mockImplementationOnce((): any => false); await expect(rule.handle({ identifier: { path: 'identifier' }})).resolves.toBe(defaultStore); }); it('throws the error if a store had a non-404 error.', async(): Promise => { - store1.resourceExists = jest.fn().mockRejectedValueOnce(new InternalServerError()); + store1.hasResource = jest.fn().mockRejectedValueOnce(new InternalServerError()); await expect(rule.handle({ identifier: { path: 'identifier' }})).rejects.toThrow(InternalServerError); }); });