core-api: remove ApiTestRegistry
This commit is contained in:
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ApiTestRegistry } from './ApiTestRegistry';
|
||||
import { createApiRef } from './ApiRef';
|
||||
|
||||
describe('ApiTestRegistry', () => {
|
||||
const aRef = createApiRef<number>({ id: 'a', description: '' });
|
||||
const bRef = createApiRef<string>({ id: 'b', description: '' });
|
||||
const cRef = createApiRef<string>({ id: 'c', description: '' });
|
||||
|
||||
it('should be created', () => {
|
||||
const registry = new ApiTestRegistry();
|
||||
expect(registry.get(aRef)).toBe(undefined);
|
||||
expect(registry.get(bRef)).toBe(undefined);
|
||||
expect(registry.get(cRef)).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should register a factory', () => {
|
||||
const registry = new ApiTestRegistry();
|
||||
registry.register({ implements: aRef, deps: {}, factory: () => 3 });
|
||||
expect(registry.get(aRef)).toBe(3);
|
||||
expect(registry.get(bRef)).toBe(undefined);
|
||||
expect(registry.get(cRef)).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should register factories with dependencies', () => {
|
||||
// 100% coverage + happy typescript = hasOwnProperty + this atrocity
|
||||
const cDeps = Object.create(
|
||||
{ c: cRef },
|
||||
{ a: { enumerable: true, value: aRef } },
|
||||
);
|
||||
cDeps.b = bRef;
|
||||
|
||||
const registry = new ApiTestRegistry();
|
||||
registry.register({ implements: aRef, deps: {}, factory: () => 3 });
|
||||
registry.register({
|
||||
implements: bRef,
|
||||
deps: { dep: aRef },
|
||||
factory: ({ dep }) => `hello ${dep}`,
|
||||
});
|
||||
registry.register({
|
||||
implements: cRef,
|
||||
deps: cDeps,
|
||||
factory: ({ a, b }) => b.repeat(a),
|
||||
});
|
||||
expect(registry.get(aRef)).toBe(3);
|
||||
expect(registry.get(bRef)).toBe('hello 3');
|
||||
expect(registry.get(cRef)).toBe('hello 3hello 3hello 3');
|
||||
});
|
||||
|
||||
it('should not allow cyclic dependencies', () => {
|
||||
const registry = new ApiTestRegistry();
|
||||
registry.register({
|
||||
implements: aRef,
|
||||
deps: { b: bRef },
|
||||
factory: () => 1,
|
||||
});
|
||||
registry.register({
|
||||
implements: bRef,
|
||||
deps: { c: cRef },
|
||||
factory: () => 'b',
|
||||
});
|
||||
registry.register({
|
||||
implements: cRef,
|
||||
deps: { a: aRef },
|
||||
factory: () => 'c',
|
||||
});
|
||||
expect(() => registry.get(aRef)).toThrow(
|
||||
'Circular dependency of api factory for apiRef{a}',
|
||||
);
|
||||
expect(() => registry.get(bRef)).toThrow(
|
||||
'Circular dependency of api factory for apiRef{b}',
|
||||
);
|
||||
expect(() => registry.get(cRef)).toThrow(
|
||||
'Circular dependency of api factory for apiRef{c}',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if dependency is not available', () => {
|
||||
const registry = new ApiTestRegistry();
|
||||
registry.register({
|
||||
implements: aRef,
|
||||
deps: { b: bRef },
|
||||
factory: () => 1,
|
||||
});
|
||||
expect(() => registry.get(aRef)).toThrow(
|
||||
'No API factory available for dependency apiRef{b} of dependent apiRef{a}',
|
||||
);
|
||||
expect(registry.get(bRef)).toBe(undefined);
|
||||
expect(registry.get(cRef)).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should only call factory func once', () => {
|
||||
const registry = new ApiTestRegistry();
|
||||
const factory = jest.fn().mockReturnValue(2);
|
||||
registry.register({ implements: aRef, deps: {}, factory });
|
||||
|
||||
expect(factory).toHaveBeenCalledTimes(0);
|
||||
expect(registry.get(aRef)).toBe(2);
|
||||
expect(factory).toHaveBeenCalledTimes(1);
|
||||
expect(registry.get(aRef)).toBe(2);
|
||||
expect(factory).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ApiRef } from './ApiRef';
|
||||
import {
|
||||
TypesToApiRefs,
|
||||
AnyApiRef,
|
||||
ApiHolder,
|
||||
ApiFactory,
|
||||
AnyApiFactory,
|
||||
} from './types';
|
||||
|
||||
export class ApiTestRegistry implements ApiHolder {
|
||||
private readonly apis = new Map<AnyApiRef, unknown>();
|
||||
private factories = new Map<AnyApiRef, AnyApiFactory>();
|
||||
|
||||
get<T>(ref: ApiRef<T>): T | undefined {
|
||||
return this.load(ref);
|
||||
}
|
||||
|
||||
register<A, D extends { [name in string]: unknown }>(
|
||||
factory: ApiFactory<A, D>,
|
||||
): ApiTestRegistry {
|
||||
this.factories.set(factory.implements, factory);
|
||||
return this;
|
||||
}
|
||||
|
||||
private load<T>(ref: ApiRef<T>, loading: AnyApiRef[] = []): T | undefined {
|
||||
const impl = this.apis.get(ref);
|
||||
if (impl) {
|
||||
return impl as T;
|
||||
}
|
||||
|
||||
const factory = this.factories.get(ref);
|
||||
if (!factory) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (loading.includes(factory.implements)) {
|
||||
throw new Error(
|
||||
`Circular dependency of api factory for ${factory.implements}`,
|
||||
);
|
||||
}
|
||||
|
||||
const deps = this.loadDeps(ref, factory.deps, [
|
||||
...loading,
|
||||
factory.implements,
|
||||
]);
|
||||
const api = factory.factory(deps);
|
||||
this.apis.set(ref, api);
|
||||
return api as T;
|
||||
}
|
||||
|
||||
private loadDeps<T>(
|
||||
dependent: ApiRef<unknown>,
|
||||
apis: TypesToApiRefs<T>,
|
||||
loading: AnyApiRef[],
|
||||
): T {
|
||||
const impls = {} as T;
|
||||
|
||||
for (const key in apis) {
|
||||
if (apis.hasOwnProperty(key)) {
|
||||
const ref = apis[key];
|
||||
|
||||
const api = this.load(ref, loading);
|
||||
if (!api) {
|
||||
throw new Error(
|
||||
`No API factory available for dependency ${ref} of dependent ${dependent}`,
|
||||
);
|
||||
}
|
||||
impls[key] = api;
|
||||
}
|
||||
}
|
||||
|
||||
return impls;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
export { ApiProvider, useApi, useApiHolder } from './ApiProvider';
|
||||
export { ApiRegistry } from './ApiRegistry';
|
||||
export { ApiTestRegistry } from './ApiTestRegistry';
|
||||
export * from './ApiRef';
|
||||
export * from './types';
|
||||
export * from './helpers';
|
||||
|
||||
Reference in New Issue
Block a user