flesh out the mock

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2024-09-10 22:21:54 +02:00
parent c40aa8798c
commit f19f848077
3 changed files with 123 additions and 97 deletions
+12 -40
View File
@@ -6,7 +6,6 @@
import { AddLocationRequest } from '@backstage/catalog-client';
import { AddLocationResponse } from '@backstage/catalog-client';
import { CatalogApi } from '@backstage/catalog-client';
import { CatalogRequestOptions } from '@backstage/catalog-client';
import { CompoundEntityRef } from '@backstage/catalog-model';
import { Entity } from '@backstage/catalog-model';
import { GetEntitiesByRefsRequest } from '@backstage/catalog-client';
@@ -24,76 +23,49 @@ import { ValidateEntityResponse } from '@backstage/catalog-client';
// @public (undocumented)
export class InMemoryCatalogClient implements CatalogApi {
constructor(options?: { entities?: Entity[] });
// (undocumented)
addLocation(
_location: AddLocationRequest,
_options?: CatalogRequestOptions | undefined,
): Promise<AddLocationResponse>;
addLocation(_location: AddLocationRequest): Promise<AddLocationResponse>;
// (undocumented)
getEntities(
_request?: GetEntitiesRequest | undefined,
_options?: CatalogRequestOptions | undefined,
): Promise<GetEntitiesResponse>;
getEntities(_request?: GetEntitiesRequest): Promise<GetEntitiesResponse>;
// (undocumented)
getEntitiesByRefs(
_request: GetEntitiesByRefsRequest,
_options?: CatalogRequestOptions | undefined,
request: GetEntitiesByRefsRequest,
): Promise<GetEntitiesByRefsResponse>;
// (undocumented)
getEntityAncestors(
_request: GetEntityAncestorsRequest,
_options?: CatalogRequestOptions | undefined,
request: GetEntityAncestorsRequest,
): Promise<GetEntityAncestorsResponse>;
// (undocumented)
getEntityByRef(
_entityRef: string | CompoundEntityRef,
_options?: CatalogRequestOptions | undefined,
entityRef: string | CompoundEntityRef,
): Promise<Entity | undefined>;
// (undocumented)
getEntityFacets(
_request: GetEntityFacetsRequest,
_options?: CatalogRequestOptions | undefined,
): Promise<GetEntityFacetsResponse>;
// (undocumented)
getLocationByEntity(
_entityRef: string | CompoundEntityRef,
_options?: CatalogRequestOptions | undefined,
): Promise<Location_2 | undefined>;
// (undocumented)
getLocationById(
_id: string,
_options?: CatalogRequestOptions | undefined,
): Promise<Location_2 | undefined>;
getLocationById(_id: string): Promise<Location_2 | undefined>;
// (undocumented)
getLocationByRef(
_locationRef: string,
_options?: CatalogRequestOptions | undefined,
): Promise<Location_2 | undefined>;
getLocationByRef(_locationRef: string): Promise<Location_2 | undefined>;
// (undocumented)
queryEntities(
_request?: QueryEntitiesRequest | undefined,
_options?: CatalogRequestOptions | undefined,
_request?: QueryEntitiesRequest,
): Promise<QueryEntitiesResponse>;
// (undocumented)
refreshEntity(
_entityRef: string,
_options?: CatalogRequestOptions | undefined,
): Promise<void>;
refreshEntity(_entityRef: string): Promise<void>;
// (undocumented)
removeEntityByUid(
_uid: string,
_options?: CatalogRequestOptions | undefined,
): Promise<void>;
removeEntityByUid(uid: string): Promise<void>;
// (undocumented)
removeLocationById(
_id: string,
_options?: CatalogRequestOptions | undefined,
): Promise<void>;
removeLocationById(_id: string): Promise<void>;
// (undocumented)
validateEntity(
_entity: Entity,
_locationRef: string,
_options?: CatalogRequestOptions | undefined,
): Promise<ValidateEntityResponse>;
}
@@ -18,7 +18,6 @@ import {
AddLocationRequest,
AddLocationResponse,
CatalogApi,
CatalogRequestOptions,
GetEntitiesByRefsRequest,
GetEntitiesByRefsResponse,
GetEntitiesRequest,
@@ -32,106 +31,111 @@ import {
QueryEntitiesResponse,
ValidateEntityResponse,
} from '@backstage/catalog-client';
import { CompoundEntityRef, Entity } from '@backstage/catalog-model';
import { NotImplementedError } from '@backstage/errors';
import {
CompoundEntityRef,
Entity,
stringifyEntityRef,
} from '@backstage/catalog-model';
import { NotFoundError, NotImplementedError } from '@backstage/errors';
/** @public */
export class InMemoryCatalogClient implements CatalogApi {
getEntities(
_request?: GetEntitiesRequest | undefined,
_options?: CatalogRequestOptions | undefined,
#entities: Entity[];
constructor(options?: { entities?: Entity[] }) {
this.#entities = options?.entities ?? [];
}
async getEntities(
_request?: GetEntitiesRequest,
): Promise<GetEntitiesResponse> {
throw new NotImplementedError('Method not implemented.');
}
getEntitiesByRefs(
_request: GetEntitiesByRefsRequest,
_options?: CatalogRequestOptions | undefined,
async getEntitiesByRefs(
request: GetEntitiesByRefsRequest,
): Promise<GetEntitiesByRefsResponse> {
throw new NotImplementedError('Method not implemented.');
const entitiesByRef = new Map<string, Entity>();
for (const entity of this.#entities) {
entitiesByRef.set(stringifyEntityRef(entity), entity);
}
const items = request.entityRefs.map(candidateRef =>
entitiesByRef.get(candidateRef),
);
// TODO(freben): Fields, filters etc
return { items };
}
queryEntities(
_request?: QueryEntitiesRequest | undefined,
_options?: CatalogRequestOptions | undefined,
async queryEntities(
_request?: QueryEntitiesRequest,
): Promise<QueryEntitiesResponse> {
throw new NotImplementedError('Method not implemented.');
}
getEntityAncestors(
_request: GetEntityAncestorsRequest,
_options?: CatalogRequestOptions | undefined,
async getEntityAncestors(
request: GetEntityAncestorsRequest,
): Promise<GetEntityAncestorsResponse> {
throw new NotImplementedError('Method not implemented.');
const entity = this.#entities.find(
e => stringifyEntityRef(e) === request.entityRef,
);
if (!entity) {
throw new NotFoundError(`Entity with ref ${request.entityRef} not found`);
}
return {
rootEntityRef: request.entityRef,
items: [{ entity, parentEntityRefs: [] }],
};
}
getEntityByRef(
_entityRef: string | CompoundEntityRef,
_options?: CatalogRequestOptions | undefined,
async getEntityByRef(
entityRef: string | CompoundEntityRef,
): Promise<Entity | undefined> {
throw new NotImplementedError('Method not implemented.');
const ref =
typeof entityRef === 'string' ? entityRef : stringifyEntityRef(entityRef);
return this.#entities.find(e => stringifyEntityRef(e) === ref);
}
removeEntityByUid(
_uid: string,
_options?: CatalogRequestOptions | undefined,
): Promise<void> {
throw new NotImplementedError('Method not implemented.');
async removeEntityByUid(uid: string): Promise<void> {
this.#entities = this.#entities.filter(e => e.metadata.uid !== uid);
}
refreshEntity(
_entityRef: string,
_options?: CatalogRequestOptions | undefined,
): Promise<void> {
throw new NotImplementedError('Method not implemented.');
}
async refreshEntity(_entityRef: string): Promise<void> {}
getEntityFacets(
async getEntityFacets(
_request: GetEntityFacetsRequest,
_options?: CatalogRequestOptions | undefined,
): Promise<GetEntityFacetsResponse> {
throw new NotImplementedError('Method not implemented.');
}
getLocationById(
_id: string,
_options?: CatalogRequestOptions | undefined,
): Promise<Location | undefined> {
async getLocationById(_id: string): Promise<Location | undefined> {
throw new NotImplementedError('Method not implemented.');
}
getLocationByRef(
_locationRef: string,
_options?: CatalogRequestOptions | undefined,
): Promise<Location | undefined> {
async getLocationByRef(_locationRef: string): Promise<Location | undefined> {
throw new NotImplementedError('Method not implemented.');
}
addLocation(
async addLocation(
_location: AddLocationRequest,
_options?: CatalogRequestOptions | undefined,
): Promise<AddLocationResponse> {
throw new NotImplementedError('Method not implemented.');
}
removeLocationById(
_id: string,
_options?: CatalogRequestOptions | undefined,
): Promise<void> {
async removeLocationById(_id: string): Promise<void> {
throw new NotImplementedError('Method not implemented.');
}
getLocationByEntity(
async getLocationByEntity(
_entityRef: string | CompoundEntityRef,
_options?: CatalogRequestOptions | undefined,
): Promise<Location | undefined> {
throw new NotImplementedError('Method not implemented.');
}
validateEntity(
async validateEntity(
_entity: Entity,
_locationRef: string,
_options?: CatalogRequestOptions | undefined,
): Promise<ValidateEntityResponse> {
throw new NotImplementedError('Method not implemented.');
}
@@ -14,19 +14,69 @@
* limitations under the License.
*/
import { createServiceFactory } from '@backstage/backend-plugin-api';
import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';
import {
ServiceRef,
createServiceFactory,
} from '@backstage/backend-plugin-api';
import { InMemoryCatalogClient } from '@backstage/catalog-client/testUtils';
import { Entity } from '@backstage/catalog-model';
import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';
// eslint-disable-next-line @backstage/no-undeclared-imports
import { ServiceMock } from '@backstage/backend-test-utils';
/** @internal */
function simpleMock<TService>(
ref: ServiceRef<TService, any>,
mockFactory: () => jest.Mocked<TService>,
): (partialImpl?: Partial<TService>) => ServiceMock<TService> {
return partialImpl => {
const mock = mockFactory();
if (partialImpl) {
for (const [key, impl] of Object.entries(partialImpl)) {
if (typeof impl === 'function') {
(mock as any)[key].mockImplementation(impl);
} else {
(mock as any)[key] = impl;
}
}
}
return Object.assign(mock, {
factory: createServiceFactory({
service: ref,
deps: {},
factory: () => mock,
}),
}) as ServiceMock<TService>;
};
}
/** @public */
export function catalogServiceMock() {}
export function catalogServiceMock(options?: { entities?: Entity[] }) {
return new InMemoryCatalogClient(options);
}
/** @public */
export namespace catalogServiceMock {
export const factory = () =>
export const factory = (options?: { entities?: Entity[] }) =>
createServiceFactory({
service: catalogServiceRef,
deps: {},
factory: () => new InMemoryCatalogClient(),
factory: () => new InMemoryCatalogClient(options),
});
export const mock = simpleMock(catalogServiceRef, () => ({
getEntities: jest.fn(),
getEntitiesByRefs: jest.fn(),
queryEntities: jest.fn(),
getEntityAncestors: jest.fn(),
getEntityByRef: jest.fn(),
removeEntityByUid: jest.fn(),
refreshEntity: jest.fn(),
getEntityFacets: jest.fn(),
getLocationById: jest.fn(),
getLocationByRef: jest.fn(),
addLocation: jest.fn(),
removeLocationById: jest.fn(),
getLocationByEntity: jest.fn(),
validateEntity: jest.fn(),
}));
}