core-api: remove ApiTestRegistry

This commit is contained in:
Patrik Oldsberg
2020-09-04 17:34:25 +02:00
parent a5741ff0aa
commit c4f794aacb
3 changed files with 0 additions and 209 deletions
@@ -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;
}
}
-1
View File
@@ -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';