Skip to content

Commit

Permalink
fix(core): update BindToFluentSyntaxImplementation.to
Browse files Browse the repository at this point in the history
update method to rely in class scope if found in metadata
  • Loading branch information
notaphplover committed Jan 10, 2025
1 parent 27ddc35 commit 9257c9a
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/thirty-nails-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@inversifyjs/core": patch
---

Updated `BindToFluentSyntaxImplementation.to` to set binding scope if found in class metadata
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { afterAll, beforeAll, describe, expect, it, jest } from '@jest/globals';

jest.mock('@inversifyjs/core');

jest.mock('../actions/getBindingId');
jest.mock('../calculations/isAnyAncestorBindingMetadata');
jest.mock('../calculations/isAnyAncestorBindingMetadataWithName');
Expand All @@ -22,9 +24,11 @@ import {
bindingScopeValues,
BindingType,
bindingTypeValues,
ClassMetadata,
ConstantValueBinding,
DynamicValueBuilder,
Factory,
getClassMetadata,
InstanceBinding,
MetadataName,
MetadataTag,
Expand All @@ -35,6 +39,7 @@ import {
} from '@inversifyjs/core';

import { Writable } from '../../common/models/Writable';
import { ClassMetadataFixtures } from '../../metadata/fixtures/ClassMetadataFixtures';
import { getBindingId } from '../actions/getBindingId';
import { isAnyAncestorBindingMetadata } from '../calculations/isAnyAncestorBindingMetadata';
import { isAnyAncestorBindingMetadataWithName } from '../calculations/isAnyAncestorBindingMetadataWithName';
Expand Down Expand Up @@ -152,8 +157,6 @@ describe(BindInFluentSyntaxImplementation.name, () => {
});

describe(BindToFluentSyntaxImplementation.name, () => {
class Foo {}

let bindingIdFixture: number;

let dynamicValueBuilderfixture: DynamicValueBuilder<unknown>;
Expand Down Expand Up @@ -204,30 +207,6 @@ describe(BindToFluentSyntaxImplementation.name, () => {
NewableFunction,
]
>([
[
'.to()',
(
bindToFluentSyntaxImplementation: BindToFluentSyntaxImplementation<unknown>,
): unknown => bindToFluentSyntaxImplementation.to(Foo),
(): Binding => ({
cache: {
isRight: false,
value: undefined,
},
id: bindingIdFixture,
implementationType: Foo,
isSatisfiedBy: expect.any(Function) as unknown as (
metadata: BindingMetadata,
) => boolean,
moduleId: containerModuleIdFixture,
onActivation: undefined,
onDeactivation: undefined,
scope: defaultScopeFixture,
serviceIdentifier: serviceIdentifierFixture,
type: bindingTypeValues.Instance,
}),
BindWhenOnFluentSyntaxImplementation,
],
[
'.toConstantValue()',
(
Expand Down Expand Up @@ -452,17 +431,28 @@ describe(BindToFluentSyntaxImplementation.name, () => {
);
});

describe('when called', () => {
describe('when called, and getClassMetadata() returns ClassMetadata with undefined scope', () => {
let result: unknown;

beforeAll(() => {
(
getClassMetadata as jest.Mock<typeof getClassMetadata>
).mockReturnValueOnce(ClassMetadataFixtures.withScopeUndefined);

result = bindToFluentSyntaxImplementation.toSelf();
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call getClassMetadata()', () => {
expect(getClassMetadata).toHaveBeenCalledTimes(1);
expect(getClassMetadata).toHaveBeenCalledWith(
serviceIdentifierFixture,
);
});

it('should call callback()', () => {
const expectedBinding: InstanceBinding<unknown> = {
cache: {
Expand Down Expand Up @@ -490,6 +480,60 @@ describe(BindToFluentSyntaxImplementation.name, () => {
expect(result).toBeInstanceOf(BindInWhenOnFluentSyntaxImplementation);
});
});

describe('when called, and getClassMetadata() returns ClassMetadata with scope', () => {
let classMetadataFixture: ClassMetadata;

let result: unknown;

beforeAll(() => {
classMetadataFixture = ClassMetadataFixtures.withScopeRequest;

(
getClassMetadata as jest.Mock<typeof getClassMetadata>
).mockReturnValueOnce(classMetadataFixture);

result = bindToFluentSyntaxImplementation.toSelf();
});

afterAll(() => {
jest.clearAllMocks();
});

it('should call getClassMetadata()', () => {
expect(getClassMetadata).toHaveBeenCalledTimes(1);
expect(getClassMetadata).toHaveBeenCalledWith(
serviceIdentifierFixture,
);
});

it('should call callback()', () => {
const expectedBinding: InstanceBinding<unknown> = {
cache: {
isRight: false,
value: undefined,
},
id: getBindingId(),
implementationType: Foo,
isSatisfiedBy: expect.any(Function) as unknown as (
metadata: BindingMetadata,
) => boolean,
moduleId: containerModuleIdFixture,
onActivation: undefined,
onDeactivation: undefined,
scope: classMetadataFixture.scope as BindingScope,
serviceIdentifier: serviceIdentifierFixture,
type: bindingTypeValues.Instance,
};

expect(callbackMock).toHaveBeenCalledTimes(1);
expect(callbackMock).toHaveBeenCalledWith(expectedBinding);
});

it('should return expected result', () => {
expect(result).toBeInstanceOf(BindInWhenOnFluentSyntaxImplementation);
});
});
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import {
bindingScopeValues,
BindingType,
bindingTypeValues,
ClassMetadata,
ConstantValueBinding,
DynamicValueBinding,
DynamicValueBuilder,
Factory,
FactoryBinding,
getClassMetadata,
InstanceBinding,
MetadataName,
MetadataTag,
Expand Down Expand Up @@ -96,6 +98,8 @@ export class BindToFluentSyntaxImplementation<T>
}

public to(type: Newable<T>): BindInWhenOnFluentSyntax<T> {
const classMetadata: ClassMetadata = getClassMetadata(type);

const binding: InstanceBinding<T> = {
cache: {
isRight: false,
Expand All @@ -107,7 +111,7 @@ export class BindToFluentSyntaxImplementation<T>
moduleId: this.#containerModuleId,
onActivation: undefined,
onDeactivation: undefined,
scope: this.#defaultScope,
scope: classMetadata.scope ?? this.#defaultScope,
serviceIdentifier: this.#serviceIdentifier,
type: bindingTypeValues.Instance,
};
Expand All @@ -124,25 +128,7 @@ export class BindToFluentSyntaxImplementation<T>
);
}

const binding: InstanceBinding<T> = {
cache: {
isRight: false,
value: undefined,
},
id: getBindingId(),
implementationType: this.#serviceIdentifier as Newable<T>,
isSatisfiedBy: BindingConstraintUtils.always,
moduleId: this.#containerModuleId,
onActivation: undefined,
onDeactivation: undefined,
scope: this.#defaultScope,
serviceIdentifier: this.#serviceIdentifier,
type: bindingTypeValues.Instance,
};

this.#callback(binding);

return new BindInWhenOnFluentSyntaxImplementation<T>(binding);
return this.to(this.#serviceIdentifier as Newable<T>);
}

public toConstantValue(value: T): BindWhenOnFluentSyntax<T> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { bindingScopeValues, ClassMetadata } from '@inversifyjs/core';

export class ClassMetadataFixtures {
public static get any(): ClassMetadata {
const fixture: ClassMetadata = {
constructorArguments: [],
lifecycle: {
postConstructMethodName: undefined,
preDestroyMethodName: undefined,
},
properties: new Map(),
scope: undefined,
};

return fixture;
}

public static get withScopeRequest(): ClassMetadata {
const fixture: ClassMetadata = {
...ClassMetadataFixtures.any,
scope: bindingScopeValues.Request,
};

return fixture;
}

public static get withScopeUndefined(): ClassMetadata {
const fixture: ClassMetadata = {
...ClassMetadataFixtures.any,
scope: undefined,
};

return fixture;
}
}

0 comments on commit 9257c9a

Please sign in to comment.