Skip to content

Commit

Permalink
feat: Implement checking for if "alias-has-registrations"
Browse files Browse the repository at this point in the history
This permits eg. creation of specialized test utils where default stubs are
registered but only if no other matching registrations are present.
  • Loading branch information
Iku-turso committed Jan 8, 2024
1 parent 2a1eaa2 commit ae1fb0a
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 3 deletions.
8 changes: 5 additions & 3 deletions packages/injectable/core/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,21 @@ export type Override = <
export interface DiContainer extends DiContainerForInjection {
purge: (injectableKey: Injectable<any, any, any>) => void;

preventSideEffects: () => void;
permitSideEffects: (
injectableKey: InjectionToken<any, any> | Injectable<any, any, any>,
) => void;

override: Override;
earlyOverride: Override;

unoverride(alias: InjectionToken<any, any> | Injectable<any, any, any>): void;

register(...injectables: Injectable<any, any, any>[]): void;

deregister(...injectables: Injectable<any, any, any>[]): void;
preventSideEffects: () => void;

hasRegistrations: (
alias: InjectionToken<any, any> | Injectable<any, any, any>,
) => boolean;
}

export type Instantiate<InjectionInstance, InstantiationParam> = {
Expand Down
6 changes: 6 additions & 0 deletions packages/injectable/core/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,3 +544,9 @@ expectType<{ someInjectable: Injectable<string, unknown, number> }>(
);

expectType<{ keys: [1, 2, 3] }>(getKeyedSingletonCompositeKey(1, 2, 3));

// given injectable, typing for "alias has registrations" is ok
expectType<boolean>(di.hasRegistrations(someInjectable));

// given token, typing for "alias has registrations" is ok
expectType<boolean>(di.hasRegistrations(someInjectionToken));
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ export default (containerId, { detectCycles = true } = {}) => {
getRelatedInjectables(alias).flatMap(injectable => [
...instancesByInjectableMap.get(injectable).values(),
]),

hasRegistrations: alias => !!getRelatedInjectables(alias).length,
};

return publicDi;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import getInjectable from '../getInjectable/getInjectable';
import createContainer from '../dependency-injection-container/createContainer';
import getInjectionToken from '../getInjectionToken/getInjectionToken';

describe('alias-has-registrations', () => {
let di;

beforeEach(() => {
di = createContainer('irrelevant');
});

describe('given an injectable with or without an injection token', () => {
let someInjectable;
let someInjectionToken;

beforeEach(() => {
someInjectionToken = getInjectionToken({
id: 'some-injection-token',
});

someInjectable = getInjectable({
id: 'some-injectable',
instantiate: () => 'irrelevant',
injectionToken: someInjectionToken,
});
});

it('given registered, when checking if the token has registrations, it does', () => {
di.register(someInjectable);

const tokenHasRegistrations = di.hasRegistrations(someInjectionToken);

expect(tokenHasRegistrations).toBe(true);
});

it('but not registered, when checking if the token has registrations, it does not', () => {
// Note: no registration.
// di.register(someInjectable);

const injectableHasRegistrations =
di.hasRegistrations(someInjectionToken);

expect(injectableHasRegistrations).toBe(false);
});

it('given registered, when checking if the injectable has registrations, it does', () => {
di.register(someInjectable);

const injectableHasRegistrations = di.hasRegistrations(someInjectable);

expect(injectableHasRegistrations).toBe(true);
});

it('but not registered, when checking if the injectable has registrations, it does not', () => {
// Note: no registration.
// di.register(someInjectable);

const injectableHasRegistrations = di.hasRegistrations(someInjectable);

expect(injectableHasRegistrations).toBe(false);
});

it('given registered, but deregistered, when checking if the token has registrations, it does not', () => {
di.register(someInjectable);
di.deregister(someInjectable);

const injectableHasRegistrations =
di.hasRegistrations(someInjectionToken);

expect(injectableHasRegistrations).toBe(false);
});

it('but not registered, when checking if the injectable has registrations, it does not', () => {
// Note: no registration.
// di.register(someInjectable);

const injectableHasRegistrations = di.hasRegistrations(someInjectable);

expect(injectableHasRegistrations).toBe(false);
});

it('given registered, but deregistered, when checking if the injectable has registrations, it does not', () => {
di.register(someInjectable);
di.deregister(someInjectable);

const injectableHasRegistrations = di.hasRegistrations(someInjectable);

expect(injectableHasRegistrations).toBe(false);
});
});
});

0 comments on commit ae1fb0a

Please sign in to comment.